コード例 #1
0
 /// <summary>
 /// 释放非托管内存
 /// </summary>
 /// <param name="seg"></param>
 public static void FreeHGlobal(KcpSegment seg)
 {
     unsafe
     {
         Marshal.FreeHGlobal((IntPtr)seg.ptr);
     }
 }
コード例 #2
0
        private static void WriteRecv(IBufferWriter <byte> writer, KcpSegment seg)
        {
            var curCount = (int)seg.len;
            var target   = writer.GetSpan(curCount);

            seg.data.CopyTo(target);
            KcpSegment.FreeHGlobal(seg);
            writer.Advance(curCount);
        }
コード例 #3
0
ファイル: KcpV2.cs プロジェクト: fwinrs/KCP-1
        /// <summary>
        /// 这个函数不检查任何参数
        /// </summary>
        /// <param name="buffer"></param>
        /// <returns></returns>
        int UncheckRecv(Span <byte> buffer)
        {
            var recover = false;

            if (rcv_queue.Count >= rcv_wnd)
            {
                recover = true;
            }

            #region merge fragment.
            /// merge fragment.

            var recvLength = 0;
            lock (rcv_queueLock)
            {
                var count = 0;
                foreach (var seg in rcv_queue)
                {
                    seg.data.CopyTo(buffer.Slice(recvLength));
                    recvLength += (int)seg.len;

                    count++;
                    int frg = seg.frg;

                    KcpSegment.FreeHGlobal(seg);
                    if (frg == 0)
                    {
                        break;
                    }
                }

                if (count > 0)
                {
                    rcv_queue.RemoveRange(0, count);
                }
            }

            #endregion

            Move_Rcv_buf_2_Rcv_queue();

            #region fast recover
            /// fast recover
            if (rcv_queue.Count < rcv_wnd && recover)
            {
                // ready to send back IKCP_CMD_WINS in ikcp_flush
                // tell remote my window size
                probe |= IKCP_ASK_TELL;
            }
            #endregion
            return(recvLength);
        }
コード例 #4
0
 // Modified by Insthync
 // 释放未托管的资源(未托管的对象)并在以下内容中替代终结器。
 // 将大型字段设置为 null。
 private void Dispose_FreeCollection(IEnumerable <KcpSegment> collection)
 {
     if (collection == null)
     {
         return;
     }
     foreach (var item in collection)
     {
         try
         {
             KcpSegment.FreeHGlobal(item);
         }
         catch (Exception)
         {
             //理论上此处不会有任何异常
         }
     }
 }
コード例 #5
0
        public int Send(ReadOnlySequence <byte> span, object option = null)
        {
            if (CheckDispose())
            {
                //检查释放
                return(-4);
            }

            if (mss <= 0)
            {
                throw new InvalidOperationException($" mss <= 0 ");
            }


            if (span.Length == 0)
            {
                return(-1);
            }
            var offset = 0;
            int count;

            #region append to previous segment in streaming mode (if possible)
            /// 基于线程安全和数据结构的等原因,移除了追加数据到最后一个包行为。
            #endregion

            #region fragment

            if (span.Length <= mss)
            {
                count = 1;
            }
            else
            {
                count = (int)(span.Length + mss - 1) / (int)mss;
            }

            if (count > IKCP_WND_RCV)
            {
                return(-2);
            }

            if (count == 0)
            {
                count = 1;
            }

            for (var i = 0; i < count; i++)
            {
                int size;
                if (span.Length - offset > mss)
                {
                    size = (int)mss;
                }
                else
                {
                    size = (int)span.Length - offset;
                }

                var seg = KcpSegment.AllocHGlobal(size);
                span.Slice(offset, size).CopyTo(seg.data);
                offset += size;
                seg.frg = (byte)(count - i - 1);
                snd_queue.Enqueue(seg);
            }

            #endregion

            return(0);
        }
コード例 #6
0
 internal override void Parse_data(KcpSegment newseg)
 {
     base.Parse_data(newseg);
     FastChechRecv();
 }
コード例 #7
0
        public int Input(ReadOnlySpan <byte> data)
        {
            if (CheckDispose())
            {
                //检查释放
                return(-4);
            }

            uint temp_una = snd_una;

            if (data.Length < IKCP_OVERHEAD)
            {
                return(-1);
            }

            var  offset = 0;
            int  flag   = 0;
            uint maxack = 0;

            while (true)
            {
                uint   ts     = 0;
                uint   sn     = 0;
                uint   length = 0;
                uint   una    = 0;
                uint   conv_  = 0;
                ushort wnd    = 0;
                byte   cmd    = 0;
                byte   frg    = 0;

                if (data.Length - offset < IKCP_OVERHEAD)
                {
                    break;
                }

                if (IsLittleEndian)
                {
                    conv_   = BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(offset));
                    offset += 4;

                    if (conv != conv_)
                    {
                        return(-1);
                    }

                    cmd     = data[offset];
                    offset += 1;
                    frg     = data[offset];
                    offset += 1;
                    wnd     = BinaryPrimitives.ReadUInt16LittleEndian(data.Slice(offset));
                    offset += 2;

                    ts      = BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(offset));
                    offset += 4;
                    sn      = BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(offset));
                    offset += 4;
                    una     = BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(offset));
                    offset += 4;
                    length  = BinaryPrimitives.ReadUInt32LittleEndian(data.Slice(offset));
                    offset += 4;
                }
                else
                {
                    conv_   = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(offset));
                    offset += 4;

                    if (conv != conv_)
                    {
                        return(-1);
                    }

                    cmd     = data[offset];
                    offset += 1;
                    frg     = data[offset];
                    offset += 1;
                    wnd     = BinaryPrimitives.ReadUInt16BigEndian(data.Slice(offset));
                    offset += 2;

                    ts      = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(offset));
                    offset += 4;
                    sn      = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(offset));
                    offset += 4;
                    una     = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(offset));
                    offset += 4;
                    length  = BinaryPrimitives.ReadUInt32BigEndian(data.Slice(offset));
                    offset += 4;
                }


                if (data.Length - offset < length || (int)length < 0)
                {
                    return(-2);
                }

                switch (cmd)
                {
                case IKCP_CMD_PUSH:
                case IKCP_CMD_ACK:
                case IKCP_CMD_WASK:
                case IKCP_CMD_WINS:
                    break;

                default:
                    return(-3);
                }

                rmt_wnd = wnd;
                Parse_una(una);
                Shrink_buf();

                if (IKCP_CMD_ACK == cmd)
                {
                    if (Itimediff(current, ts) >= 0)
                    {
                        Update_ack(Itimediff(current, ts));
                    }
                    Parse_ack(sn);
                    Shrink_buf();

                    if (flag == 0)
                    {
                        flag   = 1;
                        maxack = sn;
                    }
                    else if (Itimediff(sn, maxack) > 0)
                    {
                        maxack = sn;
                    }
                }
                else if (IKCP_CMD_PUSH == cmd)
                {
                    if (Itimediff(sn, rcv_nxt + rcv_wnd) < 0)
                    {
                        ///instead of ikcp_ack_push
                        acklist.Enqueue((sn, ts));

                        if (Itimediff(sn, rcv_nxt) >= 0)
                        {
                            var seg = KcpSegment.AllocHGlobal((int)length);
                            seg.conv = conv_;
                            seg.cmd  = cmd;
                            seg.frg  = frg;
                            seg.wnd  = wnd;
                            seg.ts   = ts;
                            seg.sn   = sn;
                            seg.una  = una;
                            //seg.len = length;  长度在分配时确定,不能改变

                            if (length > 0)
                            {
                                data.Slice(offset, (int)length).CopyTo(seg.data);
                            }

                            Parse_data(seg);
                        }
                    }
                }
                else if (IKCP_CMD_WASK == cmd)
                {
                    // ready to send back IKCP_CMD_WINS in Ikcp_flush
                    // tell remote my window size
                    probe |= IKCP_ASK_TELL;
                }
                else if (IKCP_CMD_WINS == cmd)
                {
                    // do nothing
                }
                else
                {
                    return(-3);
                }

                offset += (int)length;
            }

            if (flag != 0)
            {
                Parse_fastack(maxack);
            }

            if (Itimediff(this.snd_una, temp_una) > 0)
            {
                if (cwnd < rmt_wnd)
                {
                    var mss_ = mss;
                    if (cwnd < ssthresh)
                    {
                        cwnd++;
                        incr += mss_;
                    }
                    else
                    {
                        if (incr < mss_)
                        {
                            incr = mss_;
                        }
                        incr += (mss_ * mss_) / incr + (mss_ / 16);
                        if ((cwnd + 1) * mss_ <= incr)
                        {
                            cwnd++;
                        }
                    }
                    if (cwnd > rmt_wnd)
                    {
                        cwnd = rmt_wnd;
                        incr = rmt_wnd * mss_;
                    }
                }
            }

            return(0);
        }
コード例 #8
0
        // Modified by Insthync
        protected virtual void Dispose(bool disposing)
        {
            try
            {
                m_disposing = true;
                if (!disposedValue)
                {
                    if (disposing)
                    {
                        // 释放托管状态(托管对象)。
                        callbackHandle = null;
                        acklist        = null;
                        buffer         = null;
                    }

                    KcpSegment segment;
                    while (snd_queue != null &&
                           (snd_queue.TryDequeue(out segment) ||
                            !snd_queue.IsEmpty)
                           )
                    {
                        try
                        {
                            KcpSegment.FreeHGlobal(segment);
                        }
                        catch (Exception)
                        {
                            //理论上这里没有任何异常;
                        }
                    }
                    snd_queue = null;

                    lock (snd_bufLock)
                    {
                        Dispose_FreeCollection(snd_buf);
                        snd_buf?.Clear();
                        snd_buf = null;
                    }

                    lock (rcv_bufLock)
                    {
                        Dispose_FreeCollection(rcv_buf);
                        rcv_buf?.Clear();
                        rcv_buf = null;
                    }

                    lock (rcv_queueLock)
                    {
                        Dispose_FreeCollection(rcv_queue);
                        rcv_queue?.Clear();
                        rcv_queue = null;
                    }


                    disposedValue = true;
                }
            }
            finally
            {
                m_disposing = false;
            }
        }