Beispiel #1
0
        UdpSendStatus SendFragmentedMessage(UdpRawMessage message, IChannel channel)
        {
            message.Position = 0;
            int    mtu     = this.Mtu;
            ushort frame   = 1;
            ushort frames  = (ushort)Math.Ceiling(message.Length / (float)(mtu - Datagram.GetHeaderSize(true)));
            ushort groupId = GetNextFragementationGroupId();

            do
            {
                Debug.Assert(frame <= frames, "frame > frames");

                Datagram datagramFrag = Datagram.CreateNew(peer.Configuration.MemoryStreamPool, mtu);
                datagramFrag.Type              = MessageType.UserData;
                datagramFrag.Channel           = channel.Descriptor.Channel;
                datagramFrag.DeliveryType      = channel.Descriptor.DeliveryType;
                datagramFrag.FragmentationInfo = new Datagram.FragmentInfo(groupId, frame, frames);
                datagramFrag.ConnectionKey     = this.EndPoint.ConnectionKey;

                int toCopy = mtu - Datagram.GetHeaderSize(true);
                if (toCopy > message.Length - message.Position)
                {
                    toCopy = message.Length - message.Position;
                }
                message.CopyTo(datagramFrag.BaseStream, toCopy);

                channel.SendDatagram(datagramFrag);
                frame++;
            } while (message.Position < message.Length);

            message.Dispose();

            return(UdpSendStatus.Enqueued);
        }
Beispiel #2
0
 bool CheckCanBeSendUnfragmented(UdpRawMessage datagram)
 {
     if (datagram.Length + Datagram.GetHeaderSize(false) > Mtu)
     {
         return(false);
     }
     return(true);
 }
Beispiel #3
0
        void SendNextMtuExpand()
        {
            int nextMtu = 0;

            if (smallestFailedMtu < 0)
            {
                nextMtu = (int)(this.Mtu * 1.25);
            }
            else
            {
                nextMtu = (int)(((float)smallestFailedMtu + (float)Mtu) / 2.0f);
            }

            if (nextMtu > peer.Configuration.LimitMtu)
            {
                nextMtu = peer.Configuration.LimitMtu;
            }

            if (nextMtu == Mtu)
            {
                FixMtu();
                return;
            }

            lastMtuExpandSent = DateTime.UtcNow;
            int size        = nextMtu - Datagram.GetHeaderSize(false);
            var mtuDatagram = CreateSpecialDatagram(MessageType.ExpandMTURequest, size);

            mtuDatagram.BaseStream.SetLength(size);
            if (mtuDatagram.GetTotalSize() != nextMtu)
            {
                throw new Exception("Datagram total size doesn't match header+body size. Perhaps header size calculation failed");
            }

            logger.Debug($"Expanding MTU to {nextMtu}");
            SendDatagramAsync(mtuDatagram).ContinueWith(t => {
                if (t.Result != System.Net.Sockets.SocketError.Success)
                {
                    logger.Debug($"MTU {nextMtu} expand send failed with {t.Result}");
                    if (smallestFailedMtu < 1 || nextMtu < smallestFailedMtu)
                    {
                        smallestFailedMtu = nextMtu;
                        mtuFailedAttempts++;
                        if (mtuFailedAttempts >= peer.Configuration.MtuExpandMaxFailAttempts)
                        {
                            FixMtu();
                            return;
                        }

                        SendNextMtuExpand();
                    }
                }
            }, TaskContinuationOptions.OnlyOnRanToCompletion);
        }