private bool HasLineOfSight(UDPVoicePacket udpVoicePacket, out float losLoss) { losLoss = 0; //0 is NO LOSS if (!_serverSettings.GetSettingAsBool(ServerSettingsKeys.LOS_ENABLED)) { return(true); } SRClient transmittingClient; if (_clients.TryGetValue(udpVoicePacket.Guid, out transmittingClient)) { var myLatLng = _clientStateSingleton.PlayerCoaltionLocationMetadata.LngLngPosition; var clientLatLng = transmittingClient.LatLngPosition; if (myLatLng == null || clientLatLng == null || !myLatLng.isValid() || !clientLatLng.isValid()) { return(true); } losLoss = transmittingClient.LineOfSightLoss; return(transmittingClient.LineOfSightLoss < 1.0f); // 1.0 or greater is TOTAL loss } losLoss = 0; return(false); }
private bool HasLineOfSight(UDPVoicePacket udpVoicePacket, out float losLoss) { losLoss = 0; //0 is NO LOSS if (!_serverSettings.GetSettingAsBool(ServerSettingsKeys.LOS_ENABLED)) { return(true); } SRClient transmittingClient; if (_clientsList.TryGetValue(udpVoicePacket.Guid, out transmittingClient)) { var myPosition = _clientStateSingleton.PlayerCoaltionLocationMetadata.Position; var clientPos = transmittingClient.Position; if (((myPosition.x == 0) && (myPosition.z == 0)) || ((clientPos.x == 0) && (clientPos.z == 0))) { var myLatLng = _clientStateSingleton.PlayerCoaltionLocationMetadata.LngLngPosition; var clientLatLng = transmittingClient.LatLngPosition; //No DCS Position - do we have LotATC Position? if (((myLatLng.lat == 0) && (myLatLng.lng == 0)) || ((clientLatLng.lat == 0) && (clientLatLng.lng == 0))) { return(true); } } losLoss = transmittingClient.LineOfSightLoss; return(transmittingClient.LineOfSightLoss < 1.0f); // 1.0 or greater is TOTAL loss } losLoss = 0; return(false); }
public void EncodeMultipleFrequencyVoicePacket() { var udpVoicePacket = new UDPVoicePacket { GuidBytes = Encoding.ASCII.GetBytes("ufYS_WlLVkmFPjqCgxz6GA"), AudioPart1Bytes = new byte[] { 0, 1, 2, 3, 4, 5 }, AudioPart1Length = (ushort)6, Frequencies = new double[] { 251000000, 30000000, 251000000 }, UnitId = 1, Encryptions = new byte[] { 0, 0, 1 }, Modulations = new byte[] { 0, 1, 0 }, PacketNumber = 1 }; var encodedUdpVoicePacket = udpVoicePacket.EncodePacket(); Assert.AreEqual(80, encodedUdpVoicePacket.Length); var expectedEncodedUdpVoicePacket = new byte[80] { 80, 0, 6, 0, 30, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 128, 233, 235, 173, 65, 0, 0, 0, 0, 0, 0, 56, 156, 124, 65, 1, 0, 0, 0, 0, 128, 233, 235, 173, 65, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65 }; CollectionAssert.AreEqual(expectedEncodedUdpVoicePacket, encodedUdpVoicePacket); }
public void DecodeMultipleFrequencyVoicePacket() { var encodedUdpVoicePacket = new byte[80] { 80, 0, 6, 0, 30, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 128, 233, 235, 173, 65, 0, 0, 0, 0, 0, 0, 56, 156, 124, 65, 1, 0, 0, 0, 0, 128, 233, 235, 173, 65, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65 }; var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedUdpVoicePacket); Assert.AreEqual("ufYS_WlLVkmFPjqCgxz6GA", udpVoicePacket.Guid); CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5 }, udpVoicePacket.AudioPart1Bytes); Assert.AreEqual(6, udpVoicePacket.AudioPart1Length); CollectionAssert.AreEqual(new double[] { 251000000, 30000000, 251000000 }, udpVoicePacket.Frequencies); Assert.AreEqual((uint)1, udpVoicePacket.UnitId); CollectionAssert.AreEqual(new byte[] { 0, 0, 1 }, udpVoicePacket.Encryptions); CollectionAssert.AreEqual(new byte[] { 0, 1, 0 }, udpVoicePacket.Modulations); Assert.AreEqual((ulong)1, udpVoicePacket.PacketNumber); Assert.AreEqual((ushort)80, udpVoicePacket.PacketLength); }
public void EncodeInitialVoicePacket() { var udpVoicePacket = new UDPVoicePacket { GuidBytes = Encoding.ASCII.GetBytes("ufYS_WlLVkmFPjqCgxz6GA"), AudioPart1Bytes = new byte[] { 0, 1, 2, 3, 4, 5 }, AudioPart1Length = (ushort)6, Frequencies = new double[] { 100 }, UnitId = 1, Encryptions = new byte[] { 0 }, Modulations = new byte[] { 4 }, PacketNumber = 1 }; var encodedUdpVoicePacket = udpVoicePacket.EncodePacket(); Assert.AreEqual(60, udpVoicePacket.PacketLength); Assert.AreEqual(60, encodedUdpVoicePacket.Length); var expectedEncodedUdpVoicePacket = new byte[60] { 60, 0, 6, 0, 10, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 64, 4, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65 }; CollectionAssert.AreEqual(expectedEncodedUdpVoicePacket, encodedUdpVoicePacket); }
private bool HasLineOfSight(UDPVoicePacket udpVoicePacket, out float losLoss) { losLoss = 0; //0 is NO LOSS if (!ClientSync.ServerSettings[(int)ServerSettingType.LOS_ENABLED]) { return(true); } SRClient transmittingClient; if (_clientsList.TryGetValue(udpVoicePacket.Guid, out transmittingClient)) { var myPosition = _clientStateSingleton.DcsPlayerRadioInfo.pos; var clientPos = transmittingClient.Position; if (((myPosition.x == 0) && (myPosition.z == 0)) || ((clientPos.x == 0) && (clientPos.z == 0))) { //no real position therefore no line of Sight! return(true); } losLoss = transmittingClient.LineOfSightLoss; return(transmittingClient.LineOfSightLoss < 1.0f); // 1.0 or greater is TOTAL loss } losLoss = 0; return(false); }
public void SendMusicPacket(byte[] musicBytes) { try { if (!stop && (musicBytes != null)) { musicClient.IsBroadcasting = true; musicClient.PacketNumber += 1; // Generate packet var udpVoicePacketBlufor = new UDPVoicePacket { GuidBytes = musicClient.GuidAsciiBytes, AudioPart1Bytes = musicBytes, AudioPart1Length = (ushort)musicBytes.Length, Frequencies = musicClient.Frequencies.ToArray(), UnitId = musicClient.UnitId, Encryptions = musicClient.Encryptions.ToArray(), Modulations = musicClient.Modulations.ToArray(), PacketNumber = musicClient.PacketNumber }; var encodedUdpVoicePacketBlufor = udpVoicePacketBlufor.EncodePacket(); // Send audio audioUdpClient.Send(encodedUdpVoicePacketBlufor, encodedUdpVoicePacketBlufor.Length, serverEndPoint); } } catch (Exception ex) { Logger.Error(ex, "Error when building and sending music packet to server"); } }
private bool InRange(UDPVoicePacket udpVoicePacket, out double signalStrength) { signalStrength = 0; if (!ClientSync.ServerSettings[(int)ServerSettingType.DISTANCE_ENABLED]) { return(true); } SRClient transmittingClient; if (_clientsList.TryGetValue(udpVoicePacket.Guid, out transmittingClient)) { var myPosition = RadioDCSSyncServer.DcsPlayerRadioInfo.pos; var clientPos = transmittingClient.Position; if ((myPosition.x == 0 && myPosition.z == 0) || (clientPos.x == 0 && clientPos.z == 0)) { //no real position return(true); } signalStrength = RadioCalculator.FriisTransmissionReceivedPower( RadioCalculator.CalculateDistance(myPosition, clientPos), udpVoicePacket.Frequency); return(signalStrength > RadioCalculator.RXSensivity); } return(false); }
private bool InRange(UDPVoicePacket udpVoicePacket, out double signalStrength) { signalStrength = 0; if (!ClientSync.ServerSettings[(int)ServerSettingType.DISTANCE_ENABLED]) { return(true); } SRClient transmittingClient; if (_clientsList.TryGetValue(udpVoicePacket.Guid, out transmittingClient)) { var myPosition = _clientStateSingleton.DcsPlayerRadioInfo.pos; var clientPos = transmittingClient.Position; if (((myPosition.x == 0) && (myPosition.z == 0)) || ((clientPos.x == 0) && (clientPos.z == 0))) { //no real position return(true); } var dist = RadioCalculator.CalculateDistance(myPosition, clientPos); var max = RadioCalculator.FriisMaximumTransmissionRange(udpVoicePacket.Frequency); // % loss of signal // 0 is no loss 1.0 is full loss signalStrength = (dist / max); return(max > dist); } return(false); }
private OutgoingUDPPackets GenerateOutgoingPacket(UDPVoicePacket udpVoice, PendingPacket pendingPacket, SRClient fromClient) { var outgoingList = new HashSet <IPEndPoint>(); var guid = fromClient.ClientGuid; foreach (var client in _clientsList) { if (!client.Key.Equals(guid)) { var ip = client.Value.VoipPort; if (ip != null) { outgoingList.Add(ip); } } } if (outgoingList.Count > 0) { return(new OutgoingUDPPackets { OutgoingEndPoints = outgoingList.ToList(), ReceivedPacket = pendingPacket.RawBytes }); } else { return(null); } }
public void EncodeMultipleFrequencyVoicePacket() { var udpVoicePacket = new UDPVoicePacket { GuidBytes = Encoding.ASCII.GetBytes("ufYS_WlLVkmFPjqCgxz6GA"), AudioPart1Bytes = new byte[] { 0, 1, 2, 3, 4, 5 }, AudioPart1Length = (ushort)6, Frequencies = new double[] { 251000000, 30000000, 251000000 }, UnitId = 1, Encryptions = new byte[] { 0, 0, 1 }, Modulations = new byte[] { 0, 1, 0 }, PacketNumber = 1 }; var encodedUdpVoicePacket = udpVoicePacket.EncodePacket(); Assert.AreEqual(76, udpVoicePacket.PacketLength); Assert.AreEqual(76, encodedUdpVoicePacket.Length); var expectedEncodedUdpVoicePacket = new byte[76] { // Total packet length 76, 0, // Length of audio part 6, 0, // Length of frequencies part 30, 0, // Audio part 0, 1, 2, 3, 4, 5, // Radio frequency #1 0, 0, 0, 128, 233, 235, 173, 65, // Radio modulation #1 0, // Radio encryption #1 0, // Radio frequency #2 0, 0, 0, 0, 56, 156, 124, 65, // Radio modulation #2 1, // Radio encryption #2 0, // Radio frequency #3 0, 0, 0, 128, 233, 235, 173, 65, // Radio modulation #3 0, // Radio encryption #3 1, // Unit ID 1, 0, 0, 0, // Packet ID 1, 0, 0, 0, 0, 0, 0, 0, // Client GUID 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65 }; CollectionAssert.AreEqual(expectedEncodedUdpVoicePacket, encodedUdpVoicePacket); }
public void DecodeMultipleFrequencyVoicePacket() { var encodedUdpVoicePacket = new byte[99] { // Total packet length 99, 0, // Length of audio part 6, 0, // Length of frequencies part 30, 0, // Audio part 0, 1, 2, 3, 4, 5, // Radio frequency #1 0, 0, 0, 128, 233, 235, 173, 65, // Radio modulation #1 0, // Radio encryption #1 0, // Radio frequency #2 0, 0, 0, 0, 56, 156, 124, 65, // Radio modulation #2 1, // Radio encryption #2 0, // Radio frequency #3 0, 0, 0, 128, 233, 235, 173, 65, // Radio modulation #3 0, // Radio encryption #3 1, // Unit ID 1, 0, 0, 0, // Packet ID 1, 0, 0, 0, 0, 0, 0, 0, 254, // Transmission GUID 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65, // Client GUID 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65 }; var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedUdpVoicePacket); Assert.AreEqual("ufYS_WlLVkmFPjqCgxz6GA", udpVoicePacket.Guid); Assert.AreEqual("ufYS_WlLVkmFPjqCgxz6GA", udpVoicePacket.OriginalClientGuid); CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5 }, udpVoicePacket.AudioPart1Bytes); Assert.AreEqual(6, udpVoicePacket.AudioPart1Length); CollectionAssert.AreEqual(new double[] { 251000000, 30000000, 251000000 }, udpVoicePacket.Frequencies); Assert.AreEqual((uint)1, udpVoicePacket.UnitId); CollectionAssert.AreEqual(new byte[] { 0, 0, 1 }, udpVoicePacket.Encryptions); CollectionAssert.AreEqual(new byte[] { 0, 1, 0 }, udpVoicePacket.Modulations); Assert.AreEqual((ulong)1, udpVoicePacket.PacketNumber); Assert.AreEqual((ushort)99, udpVoicePacket.PacketLength); Assert.AreEqual((byte)254, udpVoicePacket.RetransmissionCount); }
public bool Send(byte[] bytes, int radioId) { if (bytes != null) { try { var currentlySelectedRadio = _mainClient.DcsPlayerRadioInfo.radios[radioId]; var frequencies = new List <double>(1); var encryptions = new List <byte>(1); var modulations = new List <byte>(1); frequencies.Add(currentlySelectedRadio.freq); encryptions.Add(currentlySelectedRadio.enc ? currentlySelectedRadio.encKey : (byte)0); modulations.Add((byte)currentlySelectedRadio.modulation); //generate packet var udpVoicePacket = new UDPVoicePacket { GuidBytes = _guidAsciiBytes, OriginalClientGuidBytes = _guidAsciiBytes, AudioPart1Bytes = bytes, AudioPart1Length = (ushort)bytes.Length, Frequencies = frequencies.ToArray(), UnitId = _mainClient.DcsPlayerRadioInfo.unitId, Encryptions = encryptions.ToArray(), Modulations = modulations.ToArray(), PacketNumber = _packetNumber++ }; var encodedUdpVoicePacket = udpVoicePacket.EncodePacket(); _listener.Send(encodedUdpVoicePacket, encodedUdpVoicePacket.Length, _serverEndpoint); RadioSendingState = new RadioSendingState { IsSending = true, LastSentAt = DateTime.Now.Ticks, SendingOn = radioId }; return(true); } catch (Exception e) { Logger.Error(e, $"{_mainClient.LogClientId}| Exception Sending Audio Message " + e.Message); return(false); } } if (RadioSendingState.IsSending) { RadioSendingState.IsSending = false; } return(false); }
public void EncodeInitialVoicePacket() { var udpVoicePacket = new UDPVoicePacket { GuidBytes = Encoding.ASCII.GetBytes("ufYS_WlLVkmFPjqCgxz6GA"), AudioPart1Bytes = new byte[] { 0, 1, 2, 3, 4, 5 }, AudioPart1Length = (ushort)6, Frequencies = new double[] { 100 }, UnitId = 1, Encryptions = new byte[] { 0 }, Modulations = new byte[] { 4 }, OriginalClientGuidBytes = Encoding.ASCII.GetBytes("ufYS_WlLVkmFPjqCgxz6GA"), PacketNumber = 1, RetransmissionCount = (byte)4u }; var encodedUdpVoicePacket = udpVoicePacket.EncodePacket(); Assert.AreEqual(79, udpVoicePacket.PacketLength); Assert.AreEqual(79, encodedUdpVoicePacket.Length); var expectedEncodedUdpVoicePacket = new byte[79] { // Total packet length 79, 0, // Length of audio part 6, 0, // Length of frequencies part 10, 0, // Audio part 0, 1, 2, 3, 4, 5, // Radio frequency #1 0, 0, 0, 0, 0, 0, 89, 64, // Radio modulation #1 4, // Radio encryption #1 0, // Unit ID 1, 0, 0, 0, // Packet ID 1, 0, 0, 0, 0, 0, 0, 0, //Retransmission Count, 4, // Transmission GUID 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65, // Client GUID 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65 }; for (int i = 0; i < expectedEncodedUdpVoicePacket.Length; i++) { Assert.AreEqual(expectedEncodedUdpVoicePacket[i], encodedUdpVoicePacket[i]); } CollectionAssert.AreEqual(expectedEncodedUdpVoicePacket, encodedUdpVoicePacket); }
private OutgoingVoice GenerateOutgoingPacket(UDPVoicePacket udpVoice, PendingPacket pendingPacket, SRClient fromClient) { var outgoingList = new List <IPEndPoint>(); var outgoingVoice = new OutgoingVoice { OutgoingEndPoints = outgoingList, ReceivedPacket = pendingPacket.RawBytes }; var coalitionSecurity = _serverSettings.ServerSetting[(int)ServerSettingType.COALITION_AUDIO_SECURITY]; var guid = fromClient.ClientGuid; foreach (var client in _clientsList) { if (!client.Key.Equals(guid)) { var ip = client.Value.VoipPort; // check that either coalition radio security is disabled OR the coalitions match if ((ip != null) && (!coalitionSecurity || (client.Value.Coalition == fromClient.Coalition))) { var radioInfo = client.Value.RadioInfo; if (radioInfo != null) { RadioReceivingState radioReceivingState = null; var receivingRadio = radioInfo.CanHearTransmission(udpVoice.Frequency, (RadioInformation.Modulation)udpVoice.Modulation, udpVoice.UnitId, out radioReceivingState); //only send if we can hear! if (receivingRadio != null) { outgoingList.Add(ip); } } } } else { var ip = client.Value.VoipPort; if (ip != null) { // outgoingList.Add(ip); } } } return(outgoingList.Count > 0 ? outgoingVoice : null); }
private void SendToOthers(byte[] bytes, SRClient fromClient, UDPVoicePacket udpVoicePacket) { var coalitionSecurity = _serverSettings.ServerSetting[(int)ServerSettingType.COALITION_AUDIO_SECURITY]; var guid = fromClient.ClientGuid; foreach (var client in _clientsList) { try { if (!client.Key.Equals(guid)) { var ip = client.Value.VoipPort; // check that either coalition radio security is disabled OR the coalitions match if (ip != null && (!coalitionSecurity || client.Value.Coalition == fromClient.Coalition)) { var radioInfo = client.Value.RadioInfo; if (radioInfo != null) { RadioReceivingState radioReceivingState = null; var receivingRadio = radioInfo.CanHearTransmission(udpVoicePacket.Frequency, udpVoicePacket.Modulation, udpVoicePacket.UnitId, out radioReceivingState); //only send if we can hear! if (receivingRadio != null) { _listener.Send(bytes, bytes.Length, ip); } } } } else { var ip = client.Value.VoipPort; if (ip != null) { // _listener.Send(bytes, bytes.Length, ip); } } } catch (Exception e) { // IPEndPoint ip = client.Value; // logger.Error(e, "Error sending audio UDP for client " + e.Message); SRClient value; _clientsList.TryRemove(guid, out value); } } }
private void StartPing() { Logger.Info("Pinging Server - Starting"); var thread = new Thread(() => { byte[] message = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; while (!_stop) { //wait for cancel or quit var cancelled = _pingStop.Token.WaitHandle.WaitOne(TimeSpan.FromSeconds(60)); if (cancelled) { return; } try { if (!RadioSendingState.IsSending && _listener != null && _listener.Connected) { var udpVoicePacket = new UDPVoicePacket { GuidBytes = _guidAsciiBytes, AudioPart1Bytes = message, AudioPart1Length = (ushort)message.Length, Frequency = 100, UnitId = 1, Encryption = 0, Modulation = 4, PacketNumber = 1 }.EncodePacket(); _listener.Client.Send(udpVoicePacket); } } catch (Exception e) { Logger.Error(e, "Exception Sending Audio Ping! " + e.Message); } } }); thread.Start(); }
private bool HasLineOfSight(UDPVoicePacket udpVoicePacket, out float losLoss) { losLoss = 0; //0 is NO LOSS if (!ClientSync.ServerSettings[(int)ServerSettingType.LOS_ENABLED]) { return(true); } SRClient transmittingClient; if (_clientsList.TryGetValue(udpVoicePacket.Guid, out transmittingClient)) { losLoss = transmittingClient.LineOfSightLoss; return(transmittingClient.LineOfSightLoss < 1.0f); // 1.0 or greater is TOTAL loss } losLoss = 0; return(false); }
public void DecodeInitialVoicePacket() { var encodedUdpVoicePacket = new byte[78] { // Total packet length 78, 0, // Length of audio part 6, 0, // Length of frequencies part 9, 0, // Audio part 0, 1, 2, 3, 4, 5, // Radio frequency #1 0, 0, 0, 0, 0, 0, 89, 64, // Radio modulation #1 4, // Unit ID 1, 0, 0, 0, // Packet ID 1, 0, 0, 0, 0, 0, 0, 0, //Retransmission Count, 231, // Transmission GUID 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65, // Client GUID 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65 }; var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedUdpVoicePacket); Assert.AreEqual("ufYS_WlLVkmFPjqCgxz6GA", udpVoicePacket.Guid); CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5 }, udpVoicePacket.AudioPart1Bytes); Assert.AreEqual(6, udpVoicePacket.AudioPart1Length); CollectionAssert.AreEqual(new double[] { 100 }, udpVoicePacket.Frequencies); Assert.AreEqual((int)1, udpVoicePacket.UnitId); CollectionAssert.AreEqual(new byte[] { 4 }, udpVoicePacket.Modulations); Assert.AreEqual((ulong)1, udpVoicePacket.PacketNumber); Assert.AreEqual((ushort)78, udpVoicePacket.PacketLength); Assert.AreEqual((byte)231, udpVoicePacket.RetransmissionCount); Assert.AreEqual("ufYS_WlLVkmFPjqCgxz6GA", udpVoicePacket.OriginalClientGuid); }
public bool Send(byte[] bytes, int len, double[] freq, byte[] modulation) { if (!_stop && _listener != null && (bytes != null)) //can only send if IL2 is connected { try { //generate packet var udpVoicePacket = new UDPVoicePacket { GuidBytes = _guidAsciiBytes, AudioPart1Bytes = bytes, AudioPart1Length = (ushort)bytes.Length, Frequencies = freq, UnitId = gameState.unitId, Modulations = modulation, PacketNumber = _packetNumber++, OriginalClientGuidBytes = _guidAsciiBytes, RetransmissionCount = 0, Encryptions = new byte[] { 0 }, }; var encodedUdpVoicePacket = udpVoicePacket.EncodePacket(); _listener?.Send(encodedUdpVoicePacket, encodedUdpVoicePacket.Length, new IPEndPoint(_address, _port)); } catch (Exception e) { Logger.Error(e, "Exception Sending Audio Message " + e.Message); } } else { //couldnt send } return(false); }
private void StartPing() { Logger.Info("Pinging Server - Starting"); var thread = new Thread(() => { byte[] message = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 }; while (!_stop) { Thread.Sleep(60 * 1000); try { if (!RadioSendingState.IsSending && _listener != null && _listener.Connected) { var udpVoicePacket = new UDPVoicePacket { GuidBytes = _guidAsciiBytes, AudioPart1Bytes = message, AudioPart1Length = (ushort)message.Length, Frequency = 100, UnitId = 1, Encryption = 0, Modulation = 4, PacketNumber = 1 }.EncodePacket(); _listener.Client.Send(udpVoicePacket); } } catch (Exception e) { Logger.Error(e, "Exception Sending Audio Ping! " + e.Message); } } }); thread.Start(); }
public void DecodeInitialVoicePacket() { var encodedUdpVoicePacket = new byte[60] { 60, 0, 6, 0, 10, 0, 0, 1, 2, 3, 4, 5, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 89, 64, 4, 0, 1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 117, 102, 89, 83, 95, 87, 108, 76, 86, 107, 109, 70, 80, 106, 113, 67, 103, 120, 122, 54, 71, 65 }; var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedUdpVoicePacket); Assert.AreEqual("ufYS_WlLVkmFPjqCgxz6GA", udpVoicePacket.Guid); CollectionAssert.AreEqual(new byte[] { 0, 1, 2, 3, 4, 5 }, udpVoicePacket.AudioPart1Bytes); Assert.AreEqual(6, udpVoicePacket.AudioPart1Length); CollectionAssert.AreEqual(new double[] { 100 }, udpVoicePacket.Frequencies); Assert.AreEqual((uint)1, udpVoicePacket.UnitId); CollectionAssert.AreEqual(new byte[] { 0 }, udpVoicePacket.Encryptions); CollectionAssert.AreEqual(new byte[] { 4 }, udpVoicePacket.Modulations); Assert.AreEqual((ulong)1, udpVoicePacket.PacketNumber); Assert.AreEqual((ushort)60, udpVoicePacket.PacketLength); }
public bool Send(byte[] bytes, int len) { //if either PTT is true, a microphone is available && socket connected etc if (_ready && _listener != null && _listener.Connected && (_ptt || _clientStateSingleton.DcsPlayerRadioInfo.ptt) && _clientStateSingleton.DcsPlayerRadioInfo.IsCurrent() && _clientStateSingleton.MicrophoneAvailable && (bytes != null)) //can only send if DCS is connected { try { var currentSelected = _clientStateSingleton.DcsPlayerRadioInfo.selected; //removes race condition by assigning here with the current selected changing if ((currentSelected >= 0) && (currentSelected < _clientStateSingleton.DcsPlayerRadioInfo.radios.Length)) { var radio = _clientStateSingleton.DcsPlayerRadioInfo.radios[currentSelected]; if (((radio != null) && (radio.freq > 100) && (radio.modulation != RadioInformation.Modulation.DISABLED)) || (radio.modulation == RadioInformation.Modulation.INTERCOM)) { //generate packet var udpVoicePacket = new UDPVoicePacket { GuidBytes = _guidAsciiBytes, AudioPart1Bytes = bytes, AudioPart1Length = (ushort)bytes.Length, Frequency = radio.freq, UnitId = _clientStateSingleton.DcsPlayerRadioInfo.unitId, Encryption = radio.enc ? radio.encKey : (byte)0, Modulation = (byte)radio.modulation, PacketNumber = _packetNumber++ }.EncodePacket(); //send audio _listener.Client.Send(udpVoicePacket); //not sending or really quickly switched sending if (!RadioSendingState.IsSending || (RadioSendingState.SendingOn != currentSelected)) { _audioManager.PlaySoundEffectStartTransmit(currentSelected, radio.enc && (radio.encKey > 0), radio.volume); } //set radio overlay state RadioSendingState = new RadioSendingState { IsSending = true, LastSentAt = DateTime.Now.Ticks, SendingOn = currentSelected }; return(true); } } } catch (Exception e) { Logger.Error(e, "Exception Sending Audio Message " + e.Message); } } else { if (RadioSendingState.IsSending) { RadioSendingState.IsSending = false; if (RadioSendingState.SendingOn >= 0) { var radio = _clientStateSingleton.DcsPlayerRadioInfo.radios[RadioSendingState.SendingOn]; _audioManager.PlaySoundEffectEndTransmit(RadioSendingState.SendingOn, radio.volume); } } } return(false); }
private void UdpAudioDecode() { try { while (!_stop) { try { var encodedOpusAudio = new byte[0]; _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token); var time = GetTickCount64(); //should add at the receive instead? if ((encodedOpusAudio != null) && (encodedOpusAudio.Length > 36)) { // process // check if we should play audio var myClient = IsClientMetaDataValid(_guid); if ((myClient != null) && _clientStateSingleton.DcsPlayerRadioInfo.IsCurrent()) { //Decode bytes var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio); // check the radio RadioReceivingState receivingState = null; var receivingRadio = _clientStateSingleton.DcsPlayerRadioInfo.CanHearTransmission( udpVoicePacket.Frequency, (RadioInformation.Modulation)udpVoicePacket.Modulation, udpVoicePacket.UnitId, out receivingState); //Check that we're not transmitting on this radio double receivingPowerLossPercent = 0; float lineOfSightLoss = 0; if ((receivingRadio != null) && (receivingState != null) && ((receivingRadio.modulation == RadioInformation.Modulation.INTERCOM) // INTERCOM Modulation is 2 so if its two dont bother checking LOS and Range || ( HasLineOfSight(udpVoicePacket, out lineOfSightLoss) && InRange(udpVoicePacket, out receivingPowerLossPercent) && !ShouldBlockRxAsTransmitting(receivingState.ReceivedOn) ) ) ) { // RadioReceivingState[receivingState.ReceivedOn] = receivingState; //DECODE audio int len1; var decoded = _decoder.Decode(udpVoicePacket.AudioPart1Bytes, udpVoicePacket.AudioPart1Bytes.Length, out len1); if (len1 > 0) { // for some reason if this is removed then it lags?! //guess it makes a giant buffer and only uses a little? var tmp = new byte[len1]; Buffer.BlockCopy(decoded, 0, tmp, 0, len1); //ALL GOOD! //create marker for bytes var audio = new ClientAudio { ClientGuid = udpVoicePacket.Guid, PcmAudioShort = ConversionHelpers.ByteArrayToShortArray(tmp), //Convert to Shorts! ReceiveTime = GetTickCount64(), Frequency = udpVoicePacket.Frequency, Modulation = udpVoicePacket.Modulation, Volume = receivingRadio.volume, ReceivedRadio = receivingState.ReceivedOn, UnitId = udpVoicePacket.UnitId, Encryption = udpVoicePacket.Encryption, Decryptable = (udpVoicePacket.Encryption == receivingRadio.encKey) && receivingRadio.enc, // mark if we can decrypt it RadioReceivingState = receivingState, RecevingPower = receivingPowerLossPercent, //loss of 1.0 or greater is total loss LineOfSightLoss = lineOfSightLoss, // Loss of 1.0 or greater is total loss PacketNumber = udpVoicePacket.PacketNumber }; //handle effects var radioState = RadioReceivingState[audio.ReceivedRadio]; if ((radioState == null) || radioState.PlayedEndOfTransmission || !radioState.IsReceiving) { var decrytable = audio.Decryptable || (audio.Encryption == 0); //mark that we have decrpyted encrypted audio for sound effects if (decrytable && (audio.Encryption > 0)) { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, true, audio.Volume); } else { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, false, audio.Volume); } } RadioReceivingState[audio.ReceivedRadio] = new RadioReceivingState { IsSecondary = receivingState.IsSecondary, LastReceviedAt = DateTime.Now.Ticks, PlayedEndOfTransmission = false, ReceivedOn = receivingState.ReceivedOn }; _audioManager.AddClientAudio(audio); } else { Logger.Info("Failed to decode audio from Packet"); } } } } } catch (Exception ex) { Logger.Info("Failed to decode audio from Packet"); } } } catch (OperationCanceledException) { Logger.Info("Stopped DeJitter Buffer"); } }
public void Listen() { _ready = false; //start audio processing threads var decoderThread = new Thread(UdpAudioDecode); decoderThread.Start(); var settings = SettingsStore.Instance; _inputManager.StartDetectPtt(pressed => { var radios = _clientStateSingleton.DcsPlayerRadioInfo; var radioSwitchPtt = _settings.GetClientSetting(SettingsKeys.RadioSwitchIsPTT).BoolValue; var ptt = false; foreach (var inputBindState in pressed) { if (inputBindState.IsActive) { //radio switch? if ((int)inputBindState.MainDevice.InputBind >= (int)InputBinding.Intercom && (int)inputBindState.MainDevice.InputBind <= (int)InputBinding.Switch10) { //gives you radio id if you minus 100 var radioId = (int)inputBindState.MainDevice.InputBind - 100; if (radioId < _clientStateSingleton.DcsPlayerRadioInfo.radios.Length) { var clientRadio = _clientStateSingleton.DcsPlayerRadioInfo.radios[radioId]; if (clientRadio.modulation != RadioInformation.Modulation.DISABLED && radios.control == DCSPlayerRadioInfo.RadioSwitchControls.HOTAS) { radios.selected = (short)radioId; } //turn on PTT if (radioSwitchPtt) { ptt = true; } } } else if (inputBindState.MainDevice.InputBind == InputBinding.Ptt) { ptt = true; } } } //if length is zero - no keybinds or no PTT pressed set to false _ptt = ptt; }); StartTimer(); StartPing(); //keep reconnecting until stop while (!_stop) { try { //set to false so we sent one packet to open up the radio //automatically rather than the user having to press Send hasSentVoicePacket = false; _packetNumber = 1; //reset packet number _listener = new TcpClient(); _listener.NoDelay = true; _listener.Connect(_address, _port); //initial packet to get audio setup var udpVoicePacket = new UDPVoicePacket { GuidBytes = _guidAsciiBytes, AudioPart1Bytes = new byte[] { 0, 1, 2, 3, 4, 5 }, AudioPart1Length = (ushort)6, Frequency = 100, UnitId = 1, Encryption = 0, Modulation = 4, PacketNumber = 1 }.EncodePacket(); _listener.Client.Send(udpVoicePacket); //contains short for audio packet length byte[] lengthBuffer = new byte[2]; _ready = true; Logger.Info("Connected to VOIP TCP " + _port); while (_listener.Connected && !_stop) { int received = _listener.Client.Receive(lengthBuffer, 2, SocketFlags.None); if (received == 0) { // didnt receive enough, quit. Logger.Warn( "Didnt Receive full packet for VOIP - Disconnecting & Reconnecting if next Recieve fails"); //break; } else { ushort packetLength = BitConverter.ToUInt16(new byte[2] { lengthBuffer[0], lengthBuffer[1] }, 0); byte[] audioPacketBuffer = new byte[packetLength]; //add pack in length to full buffer for packet decode audioPacketBuffer[0] = lengthBuffer[0]; audioPacketBuffer[1] = lengthBuffer[1]; received = _listener.Client.Receive(audioPacketBuffer, 2, packetLength - 2, SocketFlags.None); int offset = received + 2; int remaining = packetLength - 2 - received; while (remaining > 0 && received > 0) { received = _listener.Client.Receive(audioPacketBuffer, offset, remaining, SocketFlags.None); remaining = remaining - received; offset = offset + received; } if (remaining == 0) { _encodedAudio.Add(audioPacketBuffer); } else { //didnt receive enough - log and reconnect Logger.Warn("Didnt Receive any packet for VOIP - Disconnecting & Reconnecting"); break; } } } _ready = false; } catch (Exception e) { Logger.Error("Error with VOIP TCP Connection on port " + _port + " Reconnecting"); } try { _listener.Close(); } catch (Exception e) { } } }
public bool Send(byte[] bytes, int len) { // List of radios the transmission is sent to (can me multiple if simultaneous transmission is enabled) List <RadioInformation> transmittingRadios; //if either PTT is true, a microphone is available && socket connected etc var sendingOn = -1; if (_ready && _listener != null && _audioInputSingleton.MicrophoneAvailable && (bytes != null) && (transmittingRadios = PTTPressed(out sendingOn)).Count > 0) //can only send if IL2 is connected { try { if (transmittingRadios.Count > 0) { List <double> frequencies = new List <double>(transmittingRadios.Count); List <byte> encryptions = new List <byte>(transmittingRadios.Count); List <byte> modulations = new List <byte>(transmittingRadios.Count); for (int i = 0; i < transmittingRadios.Count; i++) { var radio = transmittingRadios[i]; // Further deduplicate transmitted frequencies if they have the same freq./modulation/encryption (caused by differently named radios) bool alreadyIncluded = false; for (int j = 0; j < frequencies.Count; j++) { if (frequencies[j] == radio.freq && modulations[j] == (byte)radio.modulation) { alreadyIncluded = true; break; } } if (alreadyIncluded) { continue; } frequencies.Add(radio.freq); encryptions.Add((byte)0); modulations.Add((byte)radio.modulation); } //generate packet var udpVoicePacket = new UDPVoicePacket { GuidBytes = _guidAsciiBytes, AudioPart1Bytes = bytes, AudioPart1Length = (ushort)bytes.Length, Frequencies = frequencies.ToArray(), UnitId = _clientStateSingleton.PlayerGameState.unitId, Modulations = modulations.ToArray(), PacketNumber = _packetNumber++, OriginalClientGuidBytes = _guidAsciiBytes }; var encodedUdpVoicePacket = udpVoicePacket.EncodePacket(); _listener.Send(encodedUdpVoicePacket, encodedUdpVoicePacket.Length, new IPEndPoint(_address, _port)); var currentlySelectedRadio = _clientStateSingleton.PlayerGameState.radios[sendingOn]; //not sending or really quickly switched sending if (currentlySelectedRadio != null && (!_clientStateSingleton.RadioSendingState.IsSending || _clientStateSingleton.RadioSendingState.SendingOn != sendingOn)) { _audioManager.PlaySoundEffectStartTransmit(sendingOn, currentlySelectedRadio.volume, currentlySelectedRadio.modulation); } //set radio overlay state _clientStateSingleton.RadioSendingState = new RadioSendingState { IsSending = true, LastSentAt = DateTime.Now.Ticks, SendingOn = sendingOn }; return(true); } } catch (Exception e) { Logger.Error(e, "Exception Sending Audio Message " + e.Message); } } else { if (_clientStateSingleton.RadioSendingState.IsSending) { _clientStateSingleton.RadioSendingState.IsSending = false; if (_clientStateSingleton.RadioSendingState.SendingOn >= 0) { var radio = _clientStateSingleton.PlayerGameState.radios[_clientStateSingleton.RadioSendingState.SendingOn]; _audioManager.PlaySoundEffectEndTransmit(_clientStateSingleton.RadioSendingState.SendingOn, radio.volume, radio.modulation); } } } return(false); }
private void UdpAudioDecode() { try { while (!_stop) { try { var encodedOpusAudio = new byte[0]; _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token); var time = DateTime.Now.Ticks; //should add at the receive instead? if ((encodedOpusAudio != null) && (encodedOpusAudio.Length >= (UDPVoicePacket.PacketHeaderLength + UDPVoicePacket.FixedPacketLength + UDPVoicePacket.FrequencySegmentLength))) { // process // check if we should play audio var myClient = IsClientMetaDataValid(_guid); if ((myClient != null)) { //Decode bytes var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio); if (udpVoicePacket != null) { var vehicleId = -1; if (_clients.TryGetValue(udpVoicePacket.Guid, out var transmittingClient)) { vehicleId = transmittingClient.GameState.vehicleId; } var globalFrequencies = _serverSettings.GlobalFrequencies; var frequencyCount = udpVoicePacket.Frequencies.Length; List <RadioReceivingPriority> radioReceivingPriorities = new List <RadioReceivingPriority>(frequencyCount); List <int> blockedRadios = CurrentlyBlockedRadios(); // Parse frequencies into receiving radio priority for selection below for (var i = 0; i < frequencyCount; i++) { RadioReceivingState state = null; bool decryptable; //Check if Global bool globalFrequency = globalFrequencies.Contains(udpVoicePacket.Frequencies[i]); var radio = _clientStateSingleton.PlayerGameState.CanHearTransmission( udpVoicePacket.Frequencies[i], (RadioInformation.Modulation)udpVoicePacket.Modulations[i], udpVoicePacket.UnitId, vehicleId, blockedRadios, out state); float losLoss = 0.0f; double receivPowerLossPercent = 0.0; if (radio != null && state != null) { if ( radio.modulation == RadioInformation.Modulation.INTERCOM || globalFrequency || (!blockedRadios.Contains(state.ReceivedOn) ) ) { radioReceivingPriorities.Add(new RadioReceivingPriority() { Frequency = udpVoicePacket.Frequencies[i], Modulation = udpVoicePacket.Modulations[i], ReceivingRadio = radio, ReceivingState = state }); } } } // Sort receiving radios to play audio on correct one radioReceivingPriorities.Sort(SortRadioReceivingPriorities); if (radioReceivingPriorities.Count > 0) { //ALL GOOD! //create marker for bytes for (int i = 0; i < radioReceivingPriorities.Count; i++) { var destinationRadio = radioReceivingPriorities[i]; var isSimultaneousTransmission = radioReceivingPriorities.Count > 1 && i > 0; var audio = new ClientAudio { ClientGuid = udpVoicePacket.Guid, EncodedAudio = udpVoicePacket.AudioPart1Bytes, //Convert to Shorts! ReceiveTime = DateTime.Now.Ticks, Frequency = destinationRadio.Frequency, Modulation = destinationRadio.Modulation, Volume = destinationRadio.ReceivingRadio.volume, ReceivedRadio = destinationRadio.ReceivingState.ReceivedOn, UnitId = udpVoicePacket.UnitId, RadioReceivingState = destinationRadio.ReceivingState, PacketNumber = udpVoicePacket.PacketNumber, OriginalClientGuid = udpVoicePacket.OriginalClientGuid }; //handle effects var radioState = _radioReceivingState[audio.ReceivedRadio]; if (!isSimultaneousTransmission && (radioState == null || radioState.PlayedEndOfTransmission || !radioState.IsReceiving)) { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, false, audio.Volume, (RadioInformation.Modulation)audio.Modulation); } var transmitterName = ""; if (_serverSettings.GetSettingAsBool(ServerSettingsKeys.SHOW_TRANSMITTER_NAME) && _globalSettings.GetClientSettingBool(GlobalSettingsKeys.ShowTransmitterName) && transmittingClient != null) { transmitterName = transmittingClient.Name; } var newRadioReceivingState = new RadioReceivingState { IsSecondary = destinationRadio.ReceivingState.IsSecondary, LastReceivedAt = DateTime.Now.Ticks, PlayedEndOfTransmission = false, ReceivedOn = destinationRadio.ReceivingState.ReceivedOn, SentBy = transmitterName }; _radioReceivingState[audio.ReceivedRadio] = newRadioReceivingState; // Only play actual audio once if (i == 0) { _audioManager.AddClientAudio(audio); } } } } } } } catch (Exception ex) { if (!_stop) { Logger.Info(ex, "Failed to decode audio from Packet"); } } } } catch (OperationCanceledException) { Logger.Info("Stopped DeJitter Buffer"); } }
private void RetransmitAudio(UDPVoicePacket udpVoicePacket, List <RadioReceivingPriority> radioReceivingPriorities) { if (udpVoicePacket.Guid == _guid) //|| udpVoicePacket.OriginalClientGuid == _guid { return; //my own transmission - throw away - stops test frequencies } //Hop count can limit the retransmission too var nodeLimit = _serverSettings.RetransmitNodeLimit; if (nodeLimit < udpVoicePacket.RetransmissionCount) { //Reached hop limit - no retransmit return; } //Check if Global List <double> globalFrequencies = _serverSettings.GlobalFrequencies; // filter radios by ability to hear it AND decryption works List <RadioReceivingPriority> retransmitOn = new List <RadioReceivingPriority>(); //artificially limit some retransmissions - if encryption fails dont retransmit //from the subset of receiving radios - find any other radios that have retransmit - and dont retransmit on any with the same frequency //to stop loops //and ignore global frequencies //and only if we can decrypt it (or no encryption) //and not received on Guard var receivingWithRetransmit = radioReceivingPriorities.Where(receivingRadio => (receivingRadio.Decryptable || (receivingRadio.Encryption == 0)) && receivingRadio.ReceivingRadio.retransmit //check global && !globalFrequencies.Any(freq => DCSPlayerRadioInfo.FreqCloseEnough(receivingRadio.ReceivingRadio.freq, freq)) && !receivingRadio.ReceivingState.IsSecondary).ToList(); //didnt receive on any radios that we could decrypt //stop if (receivingWithRetransmit.Count == 0) { return; } //radios able to retransmit var radiosWithRetransmit = _clientStateSingleton.DcsPlayerRadioInfo.radios.Where(radio => radio.retransmit); //Check we're not retransmitting through a radio we just received on? foreach (var receivingRadio in receivingWithRetransmit) { radiosWithRetransmit = radiosWithRetransmit.Where(radio => !DCSPlayerRadioInfo.FreqCloseEnough(radio.freq, receivingRadio.Frequency)); } var finalList = radiosWithRetransmit.ToList(); if (finalList.Count == 0) { //quit return; } //From the remaining list - build up a new outgoing packet var frequencies = new double[finalList.Count]; var encryptions = new byte[finalList.Count]; var modulations = new byte[finalList.Count]; for (int i = 0; i < finalList.Count; i++) { frequencies[i] = finalList[i].freq; encryptions[i] = finalList[i].enc ? (byte)finalList[i].encKey:(byte)0; modulations[i] = (byte)finalList[i].modulation; } //generate packet var relayedPacket = new UDPVoicePacket { GuidBytes = _guidAsciiBytes, AudioPart1Bytes = udpVoicePacket.AudioPart1Bytes, AudioPart1Length = udpVoicePacket.AudioPart1Length, Frequencies = frequencies, UnitId = _clientStateSingleton.DcsPlayerRadioInfo.unitId, Encryptions = encryptions, Modulations = modulations, PacketNumber = udpVoicePacket.PacketNumber, OriginalClientGuidBytes = udpVoicePacket.OriginalClientGuidBytes, RetransmissionCount = (byte)(udpVoicePacket.RetransmissionCount + 1u), }; var packet = relayedPacket.EncodePacket(); try { _listener.Send(packet, packet.Length, new IPEndPoint(_address, _port)); } catch (Exception) { } }
private void UdpAudioDecode() { try { while (!_stop) { try { var encodedOpusAudio = new byte[0]; _encodedAudio.TryTake(out encodedOpusAudio, 100000, _stopFlag.Token); var time = DateTime.Now.Ticks; //should add at the receive instead? if ((encodedOpusAudio != null) && (encodedOpusAudio.Length >= (UDPVoicePacket.PacketHeaderLength + UDPVoicePacket.FixedPacketLength + UDPVoicePacket.FrequencySegmentLength))) { // process // check if we should play audio var myClient = IsClientMetaDataValid(_guid); if ((myClient != null) && _clientStateSingleton.DcsPlayerRadioInfo.IsCurrent()) { //Decode bytes var udpVoicePacket = UDPVoicePacket.DecodeVoicePacket(encodedOpusAudio); if (udpVoicePacket != null && udpVoicePacket.Modulations[0] != 4) { var globalFrequencies = _serverSettings.GlobalFrequencies; var frequencyCount = udpVoicePacket.Frequencies.Length; List <RadioReceivingPriority> radioReceivingPriorities = new List <RadioReceivingPriority>(frequencyCount); List <int> blockedRadios = CurrentlyBlockedRadios(); // Parse frequencies into receiving radio priority for selection below for (var i = 0; i < frequencyCount; i++) { RadioReceivingState state = null; bool decryptable; //Check if Global bool globalFrequency = globalFrequencies.Contains(udpVoicePacket.Frequencies[i]); if (globalFrequency) { //remove encryption for global udpVoicePacket.Encryptions[i] = 0; } var radio = _clientStateSingleton.DcsPlayerRadioInfo.CanHearTransmission( udpVoicePacket.Frequencies[i], (RadioInformation.Modulation)udpVoicePacket.Modulations[i], udpVoicePacket.Encryptions[i], udpVoicePacket.UnitId, blockedRadios, out state, out decryptable); float losLoss = 0.0f; double receivPowerLossPercent = 0.0; if (radio != null && state != null) { if ( radio.modulation == RadioInformation.Modulation.INTERCOM || globalFrequency || ( HasLineOfSight(udpVoicePacket, out losLoss) && InRange(udpVoicePacket.Guid, udpVoicePacket.Frequencies[i], out receivPowerLossPercent) && !blockedRadios.Contains(state.ReceivedOn) ) ) { decryptable = (udpVoicePacket.Encryptions[i] == 0) || (udpVoicePacket.Encryptions[i] == radio.encKey && radio.enc); radioReceivingPriorities.Add(new RadioReceivingPriority() { Decryptable = decryptable, Encryption = udpVoicePacket.Encryptions[i], Frequency = udpVoicePacket.Frequencies[i], LineOfSightLoss = losLoss, Modulation = udpVoicePacket.Modulations[i], ReceivingPowerLossPercent = receivPowerLossPercent, ReceivingRadio = radio, ReceivingState = state }); } } } // Sort receiving radios to play audio on correct one radioReceivingPriorities.Sort(SortRadioReceivingPriorities); if (radioReceivingPriorities.Count > 0) { //ALL GOOD! //create marker for bytes for (int i = 0; i < radioReceivingPriorities.Count; i++) { var destinationRadio = radioReceivingPriorities[i]; var isSimultaneousTransmission = radioReceivingPriorities.Count > 1 && i > 0; var audio = new ClientAudio { ClientGuid = udpVoicePacket.Guid, EncodedAudio = udpVoicePacket.AudioPart1Bytes, //Convert to Shorts! ReceiveTime = DateTime.Now.Ticks, Frequency = destinationRadio.Frequency, Modulation = destinationRadio.Modulation, Volume = destinationRadio.ReceivingRadio.volume, ReceivedRadio = destinationRadio.ReceivingState.ReceivedOn, UnitId = udpVoicePacket.UnitId, Encryption = destinationRadio.Encryption, Decryptable = destinationRadio.Decryptable, // mark if we can decrypt it RadioReceivingState = destinationRadio.ReceivingState, RecevingPower = destinationRadio .ReceivingPowerLossPercent, //loss of 1.0 or greater is total loss LineOfSightLoss = destinationRadio .LineOfSightLoss, // Loss of 1.0 or greater is total loss PacketNumber = udpVoicePacket.PacketNumber }; //handle effects var radioState = RadioReceivingState[audio.ReceivedRadio]; if (!isSimultaneousTransmission && (radioState == null || radioState.PlayedEndOfTransmission || !radioState.IsReceiving)) { var audioDecryptable = audio.Decryptable || (audio.Encryption == 0); //mark that we have decrpyted encrypted audio for sound effects if (audioDecryptable && (audio.Encryption > 0)) { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, true, audio.Volume); } else { _audioManager.PlaySoundEffectStartReceive(audio.ReceivedRadio, false, audio.Volume); } } RadioReceivingState[audio.ReceivedRadio] = new RadioReceivingState { IsSecondary = destinationRadio.ReceivingState.IsSecondary, IsSimultaneous = isSimultaneousTransmission, LastReceviedAt = DateTime.Now.Ticks, PlayedEndOfTransmission = false, ReceivedOn = destinationRadio.ReceivingState.ReceivedOn }; // Only play actual audio once if (i == 0) { _audioManager.AddClientAudio(audio); } } } } } } } catch (Exception ex) { if (!_stop) { Logger.Info(ex, "Failed to decode audio from Packet"); } } } } catch (OperationCanceledException) { Logger.Info("Stopped DeJitter Buffer"); } }
public override void ChannelRead(IChannelHandlerContext context, object message) { var byteBuffer = message as IByteBuffer; if (byteBuffer != null) { byte[] udpData = new byte[byteBuffer.ReadableBytes]; byteBuffer.GetBytes(0, udpData); var decodedPacket = UDPVoicePacket.DecodeVoicePacket(udpData, false); SRClient srClient; if (_clientsList.TryGetValue(decodedPacket.Guid, out srClient)) { srClient.ClientChannelId = context.Channel.Id.AsShortText(); var spectatorAudioDisabled = _serverSettings.GetGeneralSetting(ServerSettingsKeys.SPECTATORS_AUDIO_DISABLED).BoolValue; if ((srClient.Coalition == 0) && spectatorAudioDisabled) { byteBuffer.Release(); return; } else { HashSet <string> matchingClients = new HashSet <string>(); for (int i = 0; i < decodedPacket.Frequencies.Length; i++) { // Magical ignore message 4 - just used for ping if (decodedPacket.Modulations[0] == 4) { continue; } var coalitionSecurity = _serverSettings.GetGeneralSetting(ServerSettingsKeys.COALITION_AUDIO_SECURITY).BoolValue; foreach (KeyValuePair <string, SRClient> _client in _clientsList) { //dont send to receiver if (_client.Value.ClientGuid != decodedPacket.Guid) { //check frequencies if ((!coalitionSecurity || (_client.Value.Coalition == srClient.Coalition))) { var radioInfo = _client.Value.RadioInfo; if (radioInfo != null) { RadioReceivingState radioReceivingState = null; bool decryptable; var receivingRadio = radioInfo.CanHearTransmission(decodedPacket.Frequencies[i], (RadioInformation.Modulation)decodedPacket.Modulations[i], decodedPacket.Encryptions[i], decodedPacket.UnitId, emptyBlockedRadios, out radioReceivingState, out decryptable); //only send if we can hear! if (receivingRadio != null && !matchingClients.Contains(_client.Value.ClientChannelId)) { matchingClients.Add(_client.Value.ClientChannelId); } } } } } } //send to other connected clients if (matchingClients.Count > 0) { group.WriteAndFlushAsync(message, new AllMatchingChannels(matchingClients)); } else { byteBuffer.Release(); } } } else { byteBuffer.Release(); } } }