Index: net/third_party/udt/src/buffer.cpp |
=================================================================== |
--- net/third_party/udt/src/buffer.cpp (revision 78992) |
+++ net/third_party/udt/src/buffer.cpp (working copy) |
@@ -1,652 +0,0 @@ |
-/***************************************************************************** |
-Copyright (c) 2001 - 2011, The Board of Trustees of the University of Illinois. |
-All rights reserved. |
- |
-Redistribution and use in source and binary forms, with or without |
-modification, are permitted provided that the following conditions are |
-met: |
- |
-* Redistributions of source code must retain the above |
- copyright notice, this list of conditions and the |
- following disclaimer. |
- |
-* Redistributions in binary form must reproduce the |
- above copyright notice, this list of conditions |
- and the following disclaimer in the documentation |
- and/or other materials provided with the distribution. |
- |
-* Neither the name of the University of Illinois |
- nor the names of its contributors may be used to |
- endorse or promote products derived from this |
- software without specific prior written permission. |
- |
-THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS |
-IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, |
-THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR |
-PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR |
-CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, |
-EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, |
-PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR |
-PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF |
-LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING |
-NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS |
-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
-*****************************************************************************/ |
- |
-/***************************************************************************** |
-written by |
- Yunhong Gu, last updated 02/03/2011 |
-*****************************************************************************/ |
- |
-#include <cstring> |
-#include <cmath> |
-#include "buffer.h" |
- |
-using namespace std; |
- |
-CSndBuffer::CSndBuffer(const int& size, const int& mss): |
-m_BufLock(), |
-m_pBlock(NULL), |
-m_pFirstBlock(NULL), |
-m_pCurrBlock(NULL), |
-m_pLastBlock(NULL), |
-m_pBuffer(NULL), |
-m_iNextMsgNo(1), |
-m_iSize(size), |
-m_iMSS(mss), |
-m_iCount(0) |
-{ |
- // initial physical buffer of "size" |
- m_pBuffer = new Buffer; |
- m_pBuffer->m_pcData = new char [m_iSize * m_iMSS]; |
- m_pBuffer->m_iSize = m_iSize; |
- m_pBuffer->m_pNext = NULL; |
- |
- // circular linked list for out bound packets |
- m_pBlock = new Block; |
- Block* pb = m_pBlock; |
- for (int i = 1; i < m_iSize; ++ i) |
- { |
- pb->m_pNext = new Block; |
- pb->m_iMsgNo = 0; |
- pb = pb->m_pNext; |
- } |
- pb->m_pNext = m_pBlock; |
- |
- pb = m_pBlock; |
- char* pc = m_pBuffer->m_pcData; |
- for (int i = 0; i < m_iSize; ++ i) |
- { |
- pb->m_pcData = pc; |
- pb = pb->m_pNext; |
- pc += m_iMSS; |
- } |
- |
- m_pFirstBlock = m_pCurrBlock = m_pLastBlock = m_pBlock; |
- |
- #ifndef WIN32 |
- pthread_mutex_init(&m_BufLock, NULL); |
- #else |
- m_BufLock = CreateMutex(NULL, false, NULL); |
- #endif |
-} |
- |
-CSndBuffer::~CSndBuffer() |
-{ |
- Block* pb = m_pBlock->m_pNext; |
- while (pb != m_pBlock) |
- { |
- Block* temp = pb; |
- pb = pb->m_pNext; |
- delete temp; |
- } |
- delete m_pBlock; |
- |
- while (m_pBuffer != NULL) |
- { |
- Buffer* temp = m_pBuffer; |
- m_pBuffer = m_pBuffer->m_pNext; |
- delete [] temp->m_pcData; |
- delete temp; |
- } |
- |
- #ifndef WIN32 |
- pthread_mutex_destroy(&m_BufLock); |
- #else |
- CloseHandle(m_BufLock); |
- #endif |
-} |
- |
-void CSndBuffer::addBuffer(const char* data, const int& len, const int& ttl, const bool& order) |
-{ |
- int size = len / m_iMSS; |
- if ((len % m_iMSS) != 0) |
- size ++; |
- |
- // dynamically increase sender buffer |
- while (size + m_iCount >= m_iSize) |
- increase(); |
- |
- uint64_t time = CTimer::getTime(); |
- int32_t inorder = order; |
- inorder <<= 29; |
- |
- Block* s = m_pLastBlock; |
- for (int i = 0; i < size; ++ i) |
- { |
- int pktlen = len - i * m_iMSS; |
- if (pktlen > m_iMSS) |
- pktlen = m_iMSS; |
- |
- memcpy(s->m_pcData, data + i * m_iMSS, pktlen); |
- s->m_iLength = pktlen; |
- |
- s->m_iMsgNo = m_iNextMsgNo | inorder; |
- if (i == 0) |
- s->m_iMsgNo |= 0x80000000; |
- if (i == size - 1) |
- s->m_iMsgNo |= 0x40000000; |
- |
- s->m_OriginTime = time; |
- s->m_iTTL = ttl; |
- |
- s = s->m_pNext; |
- } |
- m_pLastBlock = s; |
- |
- CGuard::enterCS(m_BufLock); |
- m_iCount += size; |
- CGuard::leaveCS(m_BufLock); |
- |
- m_iNextMsgNo ++; |
- if (m_iNextMsgNo == CMsgNo::m_iMaxMsgNo) |
- m_iNextMsgNo = 1; |
-} |
- |
-int CSndBuffer::addBufferFromFile(fstream& ifs, const int& len) |
-{ |
- int size = len / m_iMSS; |
- if ((len % m_iMSS) != 0) |
- size ++; |
- |
- // dynamically increase sender buffer |
- while (size + m_iCount >= m_iSize) |
- increase(); |
- |
- Block* s = m_pLastBlock; |
- int total = 0; |
- for (int i = 0; i < size; ++ i) |
- { |
- if (ifs.bad() || ifs.fail() || ifs.eof()) |
- break; |
- |
- int pktlen = len - i * m_iMSS; |
- if (pktlen > m_iMSS) |
- pktlen = m_iMSS; |
- |
- ifs.read(s->m_pcData, pktlen); |
- if ((pktlen = ifs.gcount()) <= 0) |
- break; |
- |
- // currently file transfer is only available in streaming mode, message is always in order, ttl = infinite |
- s->m_iMsgNo = m_iNextMsgNo | 0x20000000; |
- if (i == 0) |
- s->m_iMsgNo |= 0x80000000; |
- if (i == size - 1) |
- s->m_iMsgNo |= 0x40000000; |
- |
- s->m_iLength = pktlen; |
- s->m_iTTL = -1; |
- s = s->m_pNext; |
- |
- total += pktlen; |
- } |
- m_pLastBlock = s; |
- |
- CGuard::enterCS(m_BufLock); |
- m_iCount += size; |
- CGuard::leaveCS(m_BufLock); |
- |
- m_iNextMsgNo ++; |
- if (m_iNextMsgNo == CMsgNo::m_iMaxMsgNo) |
- m_iNextMsgNo = 1; |
- |
- return total; |
-} |
- |
-int CSndBuffer::readData(char** data, int32_t& msgno) |
-{ |
- // No data to read |
- if (m_pCurrBlock == m_pLastBlock) |
- return 0; |
- |
- *data = m_pCurrBlock->m_pcData; |
- int readlen = m_pCurrBlock->m_iLength; |
- msgno = m_pCurrBlock->m_iMsgNo; |
- |
- m_pCurrBlock = m_pCurrBlock->m_pNext; |
- |
- return readlen; |
-} |
- |
-int CSndBuffer::readData(char** data, const int offset, int32_t& msgno, int& msglen) |
-{ |
- CGuard bufferguard(m_BufLock); |
- |
- Block* p = m_pFirstBlock; |
- |
- for (int i = 0; i < offset; ++ i) |
- p = p->m_pNext; |
- |
- if ((p->m_iTTL >= 0) && ((CTimer::getTime() - p->m_OriginTime) / 1000 > (uint64_t)p->m_iTTL)) |
- { |
- msgno = p->m_iMsgNo & 0x1FFFFFFF; |
- |
- msglen = 1; |
- p = p->m_pNext; |
- bool move = false; |
- while (msgno == (p->m_iMsgNo & 0x1FFFFFFF)) |
- { |
- if (p == m_pCurrBlock) |
- move = true; |
- p = p->m_pNext; |
- if (move) |
- m_pCurrBlock = p; |
- msglen ++; |
- } |
- |
- return -1; |
- } |
- |
- *data = p->m_pcData; |
- int readlen = p->m_iLength; |
- msgno = p->m_iMsgNo; |
- |
- return readlen; |
-} |
- |
-void CSndBuffer::ackData(const int& offset) |
-{ |
- CGuard bufferguard(m_BufLock); |
- |
- for (int i = 0; i < offset; ++ i) |
- m_pFirstBlock = m_pFirstBlock->m_pNext; |
- |
- m_iCount -= offset; |
- |
- CTimer::triggerEvent(); |
-} |
- |
-int CSndBuffer::getCurrBufSize() const |
-{ |
- return m_iCount; |
-} |
- |
-void CSndBuffer::increase() |
-{ |
- int unitsize = m_pBuffer->m_iSize; |
- |
- // new physical buffer |
- Buffer* nbuf = NULL; |
- try |
- { |
- nbuf = new Buffer; |
- nbuf->m_pcData = new char [unitsize * m_iMSS]; |
- } |
- catch (...) |
- { |
- delete nbuf; |
- throw CUDTException(3, 2, 0); |
- } |
- nbuf->m_iSize = unitsize; |
- nbuf->m_pNext = NULL; |
- |
- // insert the buffer at the end of the buffer list |
- Buffer* p = m_pBuffer; |
- while (NULL != p->m_pNext) |
- p = p->m_pNext; |
- p->m_pNext = nbuf; |
- |
- // new packet blocks |
- Block* nblk = NULL; |
- try |
- { |
- nblk = new Block; |
- } |
- catch (...) |
- { |
- delete nblk; |
- throw CUDTException(3, 2, 0); |
- } |
- Block* pb = nblk; |
- for (int i = 1; i < unitsize; ++ i) |
- { |
- pb->m_pNext = new Block; |
- pb = pb->m_pNext; |
- } |
- |
- // insert the new blocks onto the existing one |
- pb->m_pNext = m_pLastBlock->m_pNext; |
- m_pLastBlock->m_pNext = nblk; |
- |
- pb = nblk; |
- char* pc = nbuf->m_pcData; |
- for (int i = 0; i < unitsize; ++ i) |
- { |
- pb->m_pcData = pc; |
- pb = pb->m_pNext; |
- pc += m_iMSS; |
- } |
- |
- m_iSize += unitsize; |
-} |
- |
-//////////////////////////////////////////////////////////////////////////////// |
- |
-CRcvBuffer::CRcvBuffer(CUnitQueue* queue, const int& bufsize): |
-m_pUnit(NULL), |
-m_iSize(bufsize), |
-m_pUnitQueue(queue), |
-m_iStartPos(0), |
-m_iLastAckPos(0), |
-m_iMaxPos(-1), |
-m_iNotch(0) |
-{ |
- m_pUnit = new CUnit* [m_iSize]; |
- for (int i = 0; i < m_iSize; ++ i) |
- m_pUnit[i] = NULL; |
-} |
- |
-CRcvBuffer::~CRcvBuffer() |
-{ |
- for (int i = 0; i < m_iSize; ++ i) |
- { |
- if (NULL != m_pUnit[i]) |
- { |
- m_pUnit[i]->m_iFlag = 0; |
- -- m_pUnitQueue->m_iCount; |
- } |
- } |
- |
- delete [] m_pUnit; |
-} |
- |
-int CRcvBuffer::addData(CUnit* unit, int offset) |
-{ |
- int pos = (m_iLastAckPos + offset) % m_iSize; |
- if (offset > m_iMaxPos) |
- m_iMaxPos = offset; |
- |
- if (NULL != m_pUnit[pos]) |
- return -1; |
- |
- m_pUnit[pos] = unit; |
- |
- unit->m_iFlag = 1; |
- ++ m_pUnitQueue->m_iCount; |
- |
- return 0; |
-} |
- |
-int CRcvBuffer::readBuffer(char* data, const int& len) |
-{ |
- int p = m_iStartPos; |
- int lastack = m_iLastAckPos; |
- int rs = len; |
- |
- while ((p != lastack) && (rs > 0)) |
- { |
- int unitsize = m_pUnit[p]->m_Packet.getLength() - m_iNotch; |
- if (unitsize > rs) |
- unitsize = rs; |
- |
- memcpy(data, m_pUnit[p]->m_Packet.m_pcData + m_iNotch, unitsize); |
- data += unitsize; |
- |
- if ((rs > unitsize) || (rs == m_pUnit[p]->m_Packet.getLength() - m_iNotch)) |
- { |
- CUnit* tmp = m_pUnit[p]; |
- m_pUnit[p] = NULL; |
- tmp->m_iFlag = 0; |
- -- m_pUnitQueue->m_iCount; |
- |
- if (++ p == m_iSize) |
- p = 0; |
- |
- m_iNotch = 0; |
- } |
- else |
- m_iNotch += rs; |
- |
- rs -= unitsize; |
- } |
- |
- m_iStartPos = p; |
- return len - rs; |
-} |
- |
-int CRcvBuffer::readBufferToFile(fstream& ofs, const int& len) |
-{ |
- int p = m_iStartPos; |
- int lastack = m_iLastAckPos; |
- int rs = len; |
- |
- while ((p != lastack) && (rs > 0)) |
- { |
- int unitsize = m_pUnit[p]->m_Packet.getLength() - m_iNotch; |
- if (unitsize > rs) |
- unitsize = rs; |
- |
- ofs.write(m_pUnit[p]->m_Packet.m_pcData + m_iNotch, unitsize); |
- if (ofs.fail()) |
- break; |
- |
- if ((rs > unitsize) || (rs == m_pUnit[p]->m_Packet.getLength() - m_iNotch)) |
- { |
- CUnit* tmp = m_pUnit[p]; |
- m_pUnit[p] = NULL; |
- tmp->m_iFlag = 0; |
- -- m_pUnitQueue->m_iCount; |
- |
- if (++ p == m_iSize) |
- p = 0; |
- |
- m_iNotch = 0; |
- } |
- else |
- m_iNotch += rs; |
- |
- rs -= unitsize; |
- } |
- |
- m_iStartPos = p; |
- |
- return len - rs; |
-} |
- |
-void CRcvBuffer::ackData(const int& len) |
-{ |
- m_iLastAckPos = (m_iLastAckPos + len) % m_iSize; |
- m_iMaxPos -= len; |
- if (m_iMaxPos < 0) |
- m_iMaxPos = 0; |
- |
- CTimer::triggerEvent(); |
-} |
- |
-int CRcvBuffer::getAvailBufSize() const |
-{ |
- // One slot must be empty in order to tell the difference between "empty buffer" and "full buffer" |
- return m_iSize - getRcvDataSize() - 1; |
-} |
- |
-int CRcvBuffer::getRcvDataSize() const |
-{ |
- if (m_iLastAckPos >= m_iStartPos) |
- return m_iLastAckPos - m_iStartPos; |
- |
- return m_iSize + m_iLastAckPos - m_iStartPos; |
-} |
- |
-void CRcvBuffer::dropMsg(const int32_t& msgno) |
-{ |
- for (int i = m_iStartPos, n = (m_iLastAckPos + m_iMaxPos) % m_iSize; i != n; i = (i + 1) % m_iSize) |
- if ((NULL != m_pUnit[i]) && (msgno == m_pUnit[i]->m_Packet.m_iMsgNo)) |
- m_pUnit[i]->m_iFlag = 3; |
-} |
- |
-int CRcvBuffer::readMsg(char* data, const int& len) |
-{ |
- int p, q; |
- bool passack; |
- if (!scanMsg(p, q, passack)) |
- return 0; |
- |
- int rs = len; |
- while (p != (q + 1) % m_iSize) |
- { |
- int unitsize = m_pUnit[p]->m_Packet.getLength(); |
- if ((rs >= 0) && (unitsize > rs)) |
- unitsize = rs; |
- |
- if (unitsize > 0) |
- { |
- memcpy(data, m_pUnit[p]->m_Packet.m_pcData, unitsize); |
- data += unitsize; |
- rs -= unitsize; |
- } |
- |
- if (!passack) |
- { |
- CUnit* tmp = m_pUnit[p]; |
- m_pUnit[p] = NULL; |
- tmp->m_iFlag = 0; |
- -- m_pUnitQueue->m_iCount; |
- } |
- else |
- m_pUnit[p]->m_iFlag = 2; |
- |
- if (++ p == m_iSize) |
- p = 0; |
- } |
- |
- if (!passack) |
- m_iStartPos = (q + 1) % m_iSize; |
- |
- return len - rs; |
-} |
- |
-int CRcvBuffer::getRcvMsgNum() |
-{ |
- int p, q; |
- bool passack; |
- return scanMsg(p, q, passack) ? 1 : 0; |
-} |
- |
-bool CRcvBuffer::scanMsg(int& p, int& q, bool& passack) |
-{ |
- // empty buffer |
- if ((m_iStartPos == m_iLastAckPos) && (m_iMaxPos <= 0)) |
- return false; |
- |
- //skip all bad msgs at the beginning |
- while (m_iStartPos != m_iLastAckPos) |
- { |
- if (NULL == m_pUnit[m_iStartPos]) |
- { |
- if (++ m_iStartPos == m_iSize) |
- m_iStartPos = 0; |
- continue; |
- } |
- |
- if ((1 == m_pUnit[m_iStartPos]->m_iFlag) && (m_pUnit[m_iStartPos]->m_Packet.getMsgBoundary() > 1)) |
- { |
- bool good = true; |
- |
- // look ahead for the whole message |
- for (int i = m_iStartPos; i != m_iLastAckPos;) |
- { |
- if ((NULL == m_pUnit[i]) || (1 != m_pUnit[i]->m_iFlag)) |
- { |
- good = false; |
- break; |
- } |
- |
- if ((m_pUnit[i]->m_Packet.getMsgBoundary() == 1) || (m_pUnit[i]->m_Packet.getMsgBoundary() == 3)) |
- break; |
- |
- if (++ i == m_iSize) |
- i = 0; |
- } |
- |
- if (good) |
- break; |
- } |
- |
- CUnit* tmp = m_pUnit[m_iStartPos]; |
- m_pUnit[m_iStartPos] = NULL; |
- tmp->m_iFlag = 0; |
- -- m_pUnitQueue->m_iCount; |
- |
- if (++ m_iStartPos == m_iSize) |
- m_iStartPos = 0; |
- } |
- |
- p = -1; // message head |
- q = m_iStartPos; // message tail |
- passack = m_iStartPos == m_iLastAckPos; |
- bool found = false; |
- |
- // looking for the first message |
- for (int i = 0, n = m_iMaxPos + getRcvDataSize(); i <= n; ++ i) |
- { |
- if ((NULL != m_pUnit[q]) && (1 == m_pUnit[q]->m_iFlag)) |
- { |
- switch (m_pUnit[q]->m_Packet.getMsgBoundary()) |
- { |
- case 3: // 11 |
- p = q; |
- found = true; |
- break; |
- |
- case 2: // 10 |
- p = q; |
- break; |
- |
- case 1: // 01 |
- if (p != -1) |
- found = true; |
- } |
- } |
- else |
- { |
- // a hole in this message, not valid, restart search |
- p = -1; |
- } |
- |
- if (found) |
- { |
- // the msg has to be ack'ed or it is allowed to read out of order, and was not read before |
- if (!passack || !m_pUnit[q]->m_Packet.getMsgOrderFlag()) |
- break; |
- |
- found = false; |
- } |
- |
- if (++ q == m_iSize) |
- q = 0; |
- |
- if (q == m_iLastAckPos) |
- passack = true; |
- } |
- |
- // no msg found |
- if (!found) |
- { |
- // if the message is larger than the receiver buffer, return part of the message |
- if ((p != -1) && ((q + 1) % m_iSize == p)) |
- found = true; |
- } |
- |
- return found; |
-} |