Esempio n. 1
0
        private List <AckItem> ExtractItems(List <Loop> po1Loop)
        {
            var items = new List <AckItem>();

            foreach (var po1 in po1Loop)
            {
                var pid = po1.Segments.FirstOrDefault(x => x.SegmentId == "PID");

                var item = new AckItem();

                item.PO101_AssignedIdentification = po1.GetElement(1);
                item.PO102_QuantityOrdered        = po1.GetIntElement(2);
                item.PO103_UnitOfMeasurement      = po1.GetElement(3);
                item.PO104_UnitPrice            = po1.GetDecimalElement(4);
                item.PO105_BasisOfUnitPriceCode = po1.GetElement(5);
                item.PO106_ProductIdQualifier   = po1.GetElement(6);
                item.PO107_ProductID            = po1.GetElement(7);
                item.PO108_ProductIdQualifier   = po1.GetElement(8);
                item.PO109_ProductID            = po1.GetElement(9);

                if (pid != null)
                {
                    item.PID01_ItemDescriptionType = pid.GetElement(1);
                    item.PID05_Description         = pid.GetElement(5);
                }

                items.Add(item);
            }

            return(items);
        }
Esempio n. 2
0
        /// <summary>Flush</summary>
        /// <param name="ackOnly">flush remain ack segments</param>
        public uint Flush(bool ackOnly)
        {
            var seg = Segment.Get(32);

            seg.conv = conv;
            seg.cmd  = CMD_ACK;
            seg.wnd  = WndUnused();
            seg.una  = rcv_nxt;

            int writeIndex = (int)reserved;

            void makeSpace(int space)
            {
                if (writeIndex + space > mtu)
                {
                    output(buffer, writeIndex);
                    writeIndex = (int)reserved;
                }
            }

            void flushBuffer()
            {
                if (writeIndex > reserved)
                {
                    output(buffer, writeIndex);
                }
            }

            // flush acknowledges
            for (int i = 0; i < ackList.Count; i++)
            {
                makeSpace(OVERHEAD);
                AckItem ack = ackList[i];
                if (ack.serialNumber >= rcv_nxt || ackList.Count - 1 == i)
                {
                    seg.sn      = ack.serialNumber;
                    seg.ts      = ack.timestamp;
                    writeIndex += seg.Encode(buffer, writeIndex);
                }
            }
            ackList.Clear();

            // flush remain ack segments
            if (ackOnly)
            {
                flushBuffer();
                return(interval);
            }

            uint current = 0;

            // probe window size (if remote window size equals zero)
            if (RmtWnd == 0)
            {
                current = CurrentMS;
                if (probe_wait == 0)
                {
                    probe_wait = PROBE_INIT;
                    ts_probe   = current + probe_wait;
                }
                else
                {
                    if (current >= ts_probe)
                    {
                        probe_wait  = Math.Max(probe_wait, PROBE_INIT);
                        probe_wait += probe_wait / 2;
                        probe_wait  = Math.Min(probe_wait, PROBE_LIMIT);
                        ts_probe    = current + probe_wait;
                        probe      |= ASK_SEND;
                    }
                }
            }
            else
            {
                ts_probe   = 0;
                probe_wait = 0;
            }

            // flush window probing commands
            if ((probe & ASK_SEND) != 0)
            {
                seg.cmd = CMD_WASK;
                makeSpace(OVERHEAD);
                writeIndex += seg.Encode(buffer, writeIndex);
            }

            if ((probe & ASK_TELL) != 0)
            {
                seg.cmd = CMD_WINS;
                makeSpace(OVERHEAD);
                writeIndex += seg.Encode(buffer, writeIndex);
            }

            probe = 0;

            // calculate window size
            uint cwnd_ = Math.Min(SendWindowMax, RmtWnd);

            if (!nocwnd)
            {
                cwnd_ = Math.Min(cwnd, cwnd_);
            }

            // sliding window, controlled by snd_nxt && sna_una+cwnd
            int newSegsCount = 0;

            for (int k = 0; k < sendQueue.Count; k++)
            {
                if (snd_nxt >= snd_una + cwnd_)
                {
                    break;
                }

                Segment newseg = sendQueue[k];
                newseg.conv = conv;
                newseg.cmd  = CMD_PUSH;
                newseg.sn   = snd_nxt;
                sendBuffer.Add(newseg);
                snd_nxt++;
                newSegsCount++;
            }

            sendQueue.RemoveRange(0, newSegsCount);

            // calculate resent
            uint resent = (uint)fastresend;

            if (fastresend <= 0)
            {
                resent = 0xffffffff;
            }

            // check for retransmissions
            current = CurrentMS;
            ulong change = 0; ulong lostSegs = 0;
            int   minrto = (int)interval;

            for (int k = 0; k < sendBuffer.Count; k++)
            {
                Segment segment  = sendBuffer[k];
                bool    needSend = false;
                if (segment.acked)
                {
                    continue;
                }
                if (segment.xmit == 0)  // initial transmit
                {
                    needSend         = true;
                    segment.rto      = rx_rto;
                    segment.resendts = current + segment.rto;
                }
                else if (segment.fastack >= resent || segment.fastack > 0 && newSegsCount == 0)  // fast retransmit
                {
                    needSend         = true;
                    segment.fastack  = 0;
                    segment.rto      = rx_rto;
                    segment.resendts = current + segment.rto;
                    change++;
                }
                else if (current >= segment.resendts) // RTO
                {
                    needSend = true;
                    if (!noDelay)
                    {
                        segment.rto += rx_rto;
                    }
                    else
                    {
                        segment.rto += rx_rto / 2;
                    }
                    segment.fastack  = 0;
                    segment.resendts = current + segment.rto;
                    lostSegs++;
                }

                if (needSend)
                {
                    current = CurrentMS;
                    segment.xmit++;
                    segment.ts  = current;
                    segment.wnd = seg.wnd;
                    segment.una = seg.una;

                    int need = OVERHEAD + segment.data.ReadableBytes;
                    makeSpace(need);
                    writeIndex += segment.Encode(buffer, writeIndex);
                    Buffer.BlockCopy(segment.data.RawBuffer, segment.data.ReaderIndex, buffer, writeIndex, segment.data.ReadableBytes);
                    writeIndex += segment.data.ReadableBytes;
                }

                // get the nearest rto
                int _rto = Utils.TimeDiff(segment.resendts, current);
                if (_rto > 0 && _rto < minrto)
                {
                    minrto = _rto;
                }
            }

            // flash remain segments
            flushBuffer();

            // cwnd update
            if (!nocwnd)
            {
                CwndUpdate(resent, change, lostSegs);
            }

            return((uint)minrto);
        }