Exemplo n.º 1
0
        // note: original HLAPI HandleBytes function handled >1 message in a while loop, but this wasn't necessary
        //       anymore because NetworkServer/NetworkClient Update both use while loops to handle >1 data events per
        //       frame already.
        //       -> in other words, we always receive 1 message per Receive call, never two.
        //       -> can be tested easily with a 1000ms send delay and then logging amount received in while loops here
        //          and in NetworkServer/Client Update. HandleBytes already takes exactly one.
        /// <summary>
        /// This function allows custom network connection classes to process data from the network before it is passed to the application.
        /// </summary>
        /// <param name="buffer">The data received.</param>
        internal void TransportReceive(ArraySegment <byte> buffer, int channelId)
        {
            // unpack message
            using (PooledNetworkReader networkReader = NetworkReaderPool.GetReader(buffer))
            {
                try
                {
                    int msgType = MessagePacker.UnpackId(networkReader);

                    if (msgType == MessagePacker.GetId <NotifyPacket>())
                    {
                        // this is a notify message, send to the notify receive
                        NotifyPacket notifyPacket = networkReader.ReadNotifyPacket();
                        ReceiveNotify(notifyPacket, networkReader, channelId);
                    }
                    else
                    {
                        // try to invoke the handler for that message
                        InvokeHandler(msgType, networkReader, channelId);
                    }
                }
                catch (InvalidDataException ex)
                {
                    logger.Log(ex.ToString());
                }
                catch (Exception ex)
                {
                    logger.LogError("Closed connection: " + this + ". Invalid message " + ex);
                    Connection?.Disconnect();
                }
            }
        }
Exemplo n.º 2
0
        /// <summary>
        /// Sends a message, but notify when it is delivered or lost
        /// </summary>
        /// <typeparam name="T">type of message to send</typeparam>
        /// <param name="message">message to send</param>
        /// <param name="token">a arbitrary object that the sender will receive with their notification</param>
        public void SendNotify <T>(T message, object token, int channelId = Channel.Unreliable)
        {
            if (sendWindow.Count == WINDOW_SIZE)
            {
                NotifyLost?.Invoke(this, token);
                return;
            }

            using (PooledNetworkWriter writer = NetworkWriterPool.GetWriter())
            {
                var notifyPacket = new NotifyPacket
                {
                    Sequence        = (ushort)sequencer.Next(),
                    ReceiveSequence = receiveSequence,
                    AckMask         = receiveMask
                };

                sendWindow.Enqueue(new PacketEnvelope
                {
                    Sequence = notifyPacket.Sequence,
                    Token    = token
                });

                MessagePacker.Pack(notifyPacket, writer);
                MessagePacker.Pack(message, writer);
                NetworkDiagnostics.OnSend(message, channelId, writer.Length, 1);
                Send(writer.ToArraySegment(), channelId);
                lastNotifySentTime = Time.unscaledTime;
            }
        }
Exemplo n.º 3
0
        internal void ReceiveNotify(NotifyPacket notifyPacket, NetworkReader networkReader, int channelId)
        {
            int sequenceDistance = (int)sequencer.Distance(notifyPacket.Sequence, receiveSequence);

            // sequence is so far out of bounds we can't save, just kick him (or her!)
            if (Math.Abs(sequenceDistance) > WINDOW_SIZE)
            {
                connection?.Disconnect();
                return;
            }

            // this message is old,  we already received
            // a newer or duplicate packet.  Discard it
            if (sequenceDistance <= 0)
            {
                return;
            }

            receiveSequence = notifyPacket.Sequence;

            if (sequenceDistance >= ACK_MASK_BITS)
            {
                receiveMask = 1;
            }
            else
            {
                receiveMask = (receiveMask << sequenceDistance) | 1;
            }

            AckPackets(notifyPacket.ReceiveSequence, notifyPacket.AckMask);

            int msgType = MessagePacker.UnpackId(networkReader);

            InvokeHandler(msgType, networkReader, channelId);

            if (Time.unscaledTime - lastNotifySentTime > NOTIFY_ACK_TIMEOUT)
            {
                SendNotify(new NotifyAck(), null, channelId);
            }
        }
Exemplo n.º 4
0
 public static void WriteNotifyPacket(this NetworkWriter writer, NotifyPacket packet)
 {
     writer.WriteUInt16(packet.Sequence);
     writer.WriteUInt16(packet.ReceiveSequence);
     writer.WriteUInt64(packet.AckMask);
 }