internal bool PreprocessPacketToClient(ArraySegment <byte> packet, HlapiConn destination)
        {
            //I have no idea if the HLAPI handles loopback. Whether it does or does not isn't important though - it's more
            //efficient to handle the loopback special case directly instead of passing through the entire network system!

            //This should never even be called if this peer is not the host!
            if (Server == null)
            {
                throw Log.CreatePossibleBugException("server packet preprocessing running, but this peer is not a server", "8f9dc0a0-1b48-4a7f-9bb6-f767b2542ab1");
            }

            //If there is no local client (e.g. this is a dedicated server) then there can't possibly be loopback
            if (Client == null)
            {
                return(false);
            }

            //Is this loopback?
            if (NetworkManager.singleton.client.connection != destination.Connection)
            {
                return(false);
            }

            //This is loopback!

            // check that we have a valid local client (in cases of startup or in-progress shutdowns)
            if (Client != null)
            {
                // Don't immediately deliver the packet, add it to a queue and deliver it next frame. This prevents the local client from executing "within" ...
                // ...the local server which can cause confusing stack traces.
                _loopbackQueue.Add(packet.CopyTo(_loopbackBuffers.Get()));
            }

            return(true);
        }
Beispiel #2
0
        /// <summary>
        /// Deliver a new encoded audio packet
        /// </summary>
        /// <remarks>It will be placed into a transfer buffer and will be moved into the actual buffer when FlushTransferBuffer is called on the audio playback thread</remarks>
        /// <param name="packet"></param>
        /// <param name="now"></param>
        /// <returns>How delayed this packet is from when it should arrive</returns>
        public float Push(VoicePacket packet, DateTime now)
        {
            Log.Trace("Received frame {0} from network", packet.SequenceNumber);

            // copy the data out of the frame, as the network thread will re-use the heap allocated things
            List <RemoteChannel> channelsCopy = null;

            if (packet.Channels != null)
            {
                channelsCopy = _channelListPool.Get();
                channelsCopy.Clear();
                channelsCopy.AddRange(packet.Channels);
            }

            var frameCopy = packet.EncodedAudioFrame.CopyTo(_bytePool.Get());

            var packetCopy = new VoicePacket(
                packet.SenderPlayerId,
                packet.PlaybackOptions.Priority,
                packet.PlaybackOptions.AmplitudeMultiplier,
                packet.PlaybackOptions.IsPositional,
                frameCopy,
                packet.SequenceNumber,
                channelsCopy
                );

            // queue the frame onto the transfer buffer
            if (!_inputBuffer.TryWrite(packetCopy))
            {
                Log.Warn("Failed to write an encoded audio packet into the input transfer buffer");
            }

            // We've received a packet but not been prepared yet, which means audio playback hasn't started yet - immediately flush the transfer buffer
            // It's safe to do this because we know playback isn't going, so the audio thread won't be accessing the buffer at the same time as we're flushing
            if (!_prepared)
            {
                FlushTransferBuffer();
            }

            // calculate how late the packet is
            if (!_firstFrameArrival.HasValue)
            {
                _firstFrameArrival = now;
                _firstFrameSeq     = packet.SequenceNumber;

                return(0);
            }
            else
            {
                var expectedTime = _firstFrameArrival.Value + TimeSpan.FromTicks(_frameDuration.Ticks * (packet.SequenceNumber - _firstFrameSeq));
                var delay        = now - expectedTime;

                return((float)delay.TotalSeconds);
            }
        }
Beispiel #3
0
        public static DissonanceNetworkMessage Deserialize([NotNull] this NetworkReader reader)
        {
            var arr = SerializationBuffers.Get();

            var length = reader.ReadUInt16();

            for (var i = 0; i < length; i++)
            {
                arr[i] = reader.ReadByte();
            }

            return(new DissonanceNetworkMessage(new ArraySegment <byte>(arr, 0, length)));
        }
Beispiel #4
0
        /// <summary>
        /// Push a new encoded audio packet
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="now"></param>
        /// <returns>How delayed this packet is from when it should arrive</returns>
        public float Push(VoicePacket packet, DateTime now)
        {
            Log.Trace("Received frame {0} from network", packet.SequenceNumber);

            // copy the data out of the frame, as the network thread will re-use the heap allocated things
            List <RemoteChannel> channelsCopy = null;

            if (packet.Channels != null)
            {
                channelsCopy = _channelListPool.Get();
                channelsCopy.Clear();
                channelsCopy.AddRange(packet.Channels);
            }

            var frameCopy = packet.EncodedAudioFrame.CopyTo(_bytePool.Get());

            var packetCopy = new VoicePacket(
                packet.SenderPlayerId,
                packet.PlaybackOptions.Priority,
                packet.PlaybackOptions.AmplitudeMultiplier,
                packet.PlaybackOptions.IsPositional,
                frameCopy,
                packet.SequenceNumber,
                channelsCopy
                );

            // queue the frame onto the transfer buffer
            if (!_inputBuffer.TryWrite(packetCopy))
            {
                Log.Warn("Failed to write an encoded audio packet into the input transfer buffer");
            }

            // calculate how late the packet is
            if (!_firstFrameArrival.HasValue)
            {
                _firstFrameArrival = now;
                _firstFrameSeq     = packet.SequenceNumber;

                return(0);
            }
            else
            {
                var expectedTime = _firstFrameArrival.Value + TimeSpan.FromTicks(_frameDuration.Ticks * (packet.SequenceNumber - _firstFrameSeq));
                var delay        = now - expectedTime;

                return((float)delay.TotalSeconds);
            }
        }
        private void EnqueueP2P(ushort localId, [NotNull] ICollection <ClientInfo <TPeer?> > destinations, [NotNull] ICollection <KeyValuePair <List <ClientInfo <TPeer?> >, ArraySegment <byte> > > queue, ArraySegment <byte> packet)
        {
            if (packet.Array == null)
            {
                throw new ArgumentNullException("packet");
            }
            if (destinations == null)
            {
                throw new ArgumentNullException("destinations");
            }
            if (queue == null)
            {
                throw new ArgumentNullException("queue");
            }

            //early exit
            if (destinations.Count == 0)
            {
                return;
            }

            //Copy destinations into a new list we're allowed to mutate
            var dests = _listPool.Get();

            dests.Clear();
            dests.AddRange(destinations);

            //Make sure we don't send to ourselves
            for (var i = 0; i < dests.Count; i++)
            {
                if (dests[i].PlayerId == localId)
                {
                    dests.RemoveAt(i);
                    break;
                }
            }

            //If we were only trying to send to ourself we can early exit now
            if (dests.Count == 0)
            {
                _listPool.Put(dests);
                return;
            }

            //Add to queue to send next update
            queue.Add(new KeyValuePair <List <ClientInfo <TPeer?> >, ArraySegment <byte> >(dests, packet));
        }
Beispiel #6
0
        /// <summary>
        /// Push a new encoded audio packet
        /// </summary>
        /// <param name="packet"></param>
        /// <param name="now"></param>
        /// <returns>How delayed this packet is from when it should arrive</returns>
        public float Push(VoicePacket packet, DateTime now)
        {
            Log.Trace("Received frame {0} from network", packet.SequenceNumber);

            // copy the data out of the frame, as the network thread will re-use the array
            var array = _bytePool.Get();
            var frame = packet.EncodedAudioFrame.CopyTo(array);

            // queue the frame onto the transfer buffer
            var copy = new EncodedAudio(packet.SequenceNumber, frame);

            if (!_inputBuffer.Write(copy))
            {
                Log.Warn("Failed to write an encoded audio packet into the input transfer buffer");
            }

            //Copy across the stream metadata
            //N.b. doing this means the metadata is surfaced <buffer length> too early
            Priority   = packet.Priority;
            Positional = packet.Positional;

            // calculate how late the packet is
            if (!_firstFrameArrival.HasValue)
            {
                _firstFrameArrival = now;
                _firstFrameSeq     = packet.SequenceNumber;

                return(0);
            }
            else
            {
                var expectedTime = _firstFrameArrival.Value + TimeSpan.FromTicks(_frameDuration.Ticks * (packet.SequenceNumber - _firstFrameSeq));
                var delay        = now - expectedTime;

                return((float)delay.TotalSeconds);
            }
        }
Beispiel #7
0
 public static Coroutine <T> Create()
 {
     return(Pool.Get());
 }
Beispiel #8
0
 public float[] GetFrameBuffer()
 {
     return(_inputBufferSource.Get());
 }
 public DissonanceNetworkMessage(ArraySegment <byte> packet)
 {
     //We are not allowed to keep a reference to `packet` beyond this point, immediately copy it into a temporary buffer
     Data = packet.CopyTo(SerializationBuffers.Get());
 }