private int processData(CUnit unit) { CPacket packet = unit.m_Packet; // Just heard from the peer, reset the expiration count. m_iEXPCount = 1; m_ullEXPInt = m_ullMinEXPInt; if (CSeqNo.incseq(m_iSndCurrSeqNo) == m_iSndLastAck) { CClock.rdtsc(m_ullNextEXPTime); if (!m_pCC.m_bUserDefinedRTO) m_ullNextEXPTime += m_ullEXPInt; else m_ullNextEXPTime += m_pCC.m_iRTO * m_ullCPUFrequency; } m_pCC.onPktReceived(&packet); ++ m_iPktCount; // update time information m_pRcvTimeWindow.onPktArrival(); // check if it is probing packet pair if (0 == (packet.m_iSeqNo & 0xF)) m_pRcvTimeWindow.probe1Arrival(); else if (1 == (packet.m_iSeqNo & 0xF)) m_pRcvTimeWindow.probe2Arrival(); ++ m_llTraceRecv; ++ m_llRecvTotal; Int32 offset = CSeqNo.seqoff(m_iRcvLastAck, packet.m_iSeqNo); if ((offset < 0) || (offset >= m_pRcvBuffer.getAvailBufSize())) return -1; if (m_pRcvBuffer.addData(unit, offset) < 0) return -1; // Loss detection. if (CSeqNo.seqcmp(packet.m_iSeqNo, CSeqNo.incseq(m_iRcvCurrSeqNo)) > 0) { // If loss found, insert them to the receiver loss list m_pRcvLossList.insert(CSeqNo.incseq(m_iRcvCurrSeqNo), CSeqNo.decseq(packet.m_iSeqNo)); // pack loss list for NAK Int32[] lossdata = new int[2]; lossdata[0] = CSeqNo.incseq(m_iRcvCurrSeqNo) | 0x80000000; lossdata[1] = CSeqNo.decseq(packet.m_iSeqNo); // Generate loss report immediately. sendCtrl(3, null, lossdata, (CSeqNo.incseq(m_iRcvCurrSeqNo) == CSeqNo.decseq(packet.m_iSeqNo)) ? 1 : 2); m_iTraceRcvLoss += CSeqNo.seqlen(m_iRcvCurrSeqNo, packet.m_iSeqNo) - 2; } // This is not a regular fixed size packet... //an irregular sized packet usually indicates the end of a message, so send an ACK immediately if (packet.getLength() != m_iPayloadSize) CClock.rdtsc(m_ullNextACKTime); // Update the current largest sequence number that has been received. // Or it is a retransmitted packet, remove it from receiver loss list. if (CSeqNo.seqcmp(packet.m_iSeqNo, m_iRcvCurrSeqNo) > 0) m_iRcvCurrSeqNo = packet.m_iSeqNo; else m_pRcvLossList.remove(packet.m_iSeqNo); return 0; }
// Functionality: // Increase (double) the unit queue size. // Parameters: // None. // Returned value: // 0: success, -1: failure. public int increase() { // adjust/correct m_iCount int real_count = 0; CQEntry p = m_pQEntry; while (p != null) { CUnit u = p.m_pUnit; for (CUnit end = u + p.m_iSize; u != end; ++u) if (u.m_iFlag != 0) ++real_count; if (p == m_pLastQueue) p = null; else p = p.m_pNext; } m_iCount = real_count; if ((double)(m_iCount) / m_iSize < 0.9) return -1; CQEntry tempq = null; CUnit tempu = null; IntPtr tempb = IntPtr.Zero; // all queues have the same size int size = m_pQEntry.m_iSize; try { tempq = new CQEntry(); tempu = new CUnit[size]; tempb = new char[size * m_iMSS]; } catch (Exception e) { tempq.Dispose(); tempu.Dispose(); tempb.Dispose(); //delete tempq; //delete [] tempu; //delete [] tempb; return -1; } for (int i = 0; i < size; ++i) { tempu[i].m_iFlag = 0; tempu[i].m_Packet.m_pcData = tempb + i * m_iMSS; } tempq.m_pUnit = tempu; tempq.m_pBuffer = tempb; tempq.m_iSize = size; m_pLastQueue.m_pNext = tempq; m_pLastQueue = tempq; m_pLastQueue.m_pNext = m_pQEntry; m_iSize += size; return 0; }
// Functionality: // find an available unit for incoming packet. // Parameters: // None. // Returned value: // Pointer to the available unit, null if not found. public CUnit getNextAvailUnit() { if (m_iCount * 10 > m_iSize * 9) increase(); if (m_iCount >= m_iSize) return null; CQEntry entrance = m_pCurrQueue; do { for (CUnit sentinel = m_pCurrQueue.m_pUnit + m_pCurrQueue.m_iSize - 1; m_pAvailUnit != sentinel; ++m_pAvailUnit) if (m_pAvailUnit.m_iFlag == 0) return m_pAvailUnit; if (m_pCurrQueue.m_pUnit.m_iFlag == 0) { m_pAvailUnit = m_pCurrQueue.m_pUnit; return m_pAvailUnit; } m_pCurrQueue = m_pCurrQueue.m_pNext; m_pAvailUnit = m_pCurrQueue.m_pUnit; } while (m_pCurrQueue != entrance); increase(); return null; }
public AddressFamily m_iIPversion; // IP version #region Constructor - Destructor //public CUnitQueue() //{ //} //~CUnitQueue() //{ // CQEntry p = m_pQEntry; // while (p != null) // { // CQEntry q = p; // if (p == m_pLastQueue) // p = null; // else // p = p.m_pNext; // q.Dispose(); // } //} #endregion // Functionality: // Initialize the unit queue. // Parameters: // 1) [in] size: queue size // 2) [in] mss: maximum segment size // 3) [in] version: IP version // Returned value: // 0: success, -1: failure. public int init(int size, int mss, AddressFamily version) { CQEntry tempq = null; CUnit tempu = null; IntPtr tempb = IntPtr.Zero; try { tempq = new CQEntry(); tempu = new CUnit[size]; tempb = new char[size * mss]; } catch (Exception e) { //tempq.Dispose(); // tempu.Dispose(); // tempb.Dispose(); return -1; } for (int i = 0; i < size; ++i) { tempu[i].m_iFlag = 0; tempu[i].m_Packet.m_pcData = tempb + i * mss; } tempq.m_pUnit = tempu; tempq.m_pBuffer = tempb; tempq.m_iSize = size; m_pQEntry = m_pCurrQueue = m_pLastQueue = tempq; m_pQEntry.m_pNext = m_pQEntry; m_pAvailUnit = m_pCurrQueue.m_pUnit; m_iSize = size; m_iMSS = mss; m_iIPversion = version; return 0; }