📄 core.cpp
字号:
m_iSndLastAck = req->m_iISN; m_iSndLastDataAck = req->m_iISN; m_iSndCurrSeqNo = req->m_iISN - 1; // Inform the server my configurations. request.pack(0, NULL, reqdata, sizeof(CHandShake)); // ID = 0, connection request request.m_iID = 0; // Wait for the negotiated configurations from the peer side. response.pack(0, NULL, resdata, sizeof(CHandShake)); uint64_t timeo = 3000000; if (m_bRendezvous) timeo *= 10; uint64_t entertime = CTimer::getTime(); CUDTException e(0, 0); while (!m_bClosing) { m_pSndQueue->sendto(serv_addr, request); response.setLength(m_iPayloadSize); if (m_pRcvQueue->recvfrom(m_SocketID, response) > 0) { if ((1 != response.getFlag()) || (0 != response.getType())) response.setLength(-1); if (m_bRendezvous) { // regular connect should NOT communicate with rendezvous connect // rendezvous connect require 3-way handshake if (1 == res->m_iReqType) response.setLength(-1); else if (0 == res->m_iReqType) { req->m_iReqType = -1; request.m_iID = res->m_iID; response.setLength(-1); } } } if ((response.getLength() > 0) && (res->m_iReqType < 0)) break; if (CTimer::getTime() - entertime > timeo) { // timeout e = CUDTException(1, 1, 0); break; } } delete [] reqdata; if (e.getErrorCode() == 0) { if (m_bClosing) // if the socket is closed before connection... e = CUDTException(1); else if (1002 == res->m_iReqType) // connection request rejected e = CUDTException(1, 2, 0); else if ((!m_bRendezvous) && (m_iISN != res->m_iISN)) // secuity check e = CUDTException(1, 4, 0); } if (e.getErrorCode() != 0) { // connection failure, clean up and throw exception delete [] resdata; if (m_bRendezvous) m_pRcvQueue->m_pRendezvousQueue->remove(m_SocketID); throw e; } // Got it. Re-configure according to the negotiated values. m_iMSS = res->m_iMSS; m_iFlowWindowSize = res->m_iFlightFlagSize; m_iPktSize = m_iMSS - 28; m_iPayloadSize = m_iPktSize - CPacket::m_iPktHdrSize; m_iPeerISN = res->m_iISN; m_iRcvLastAck = res->m_iISN; m_iRcvLastAckAck = res->m_iISN; m_iRcvCurrSeqNo = res->m_iISN - 1; m_PeerID = res->m_iID; delete [] resdata; // Prepare all data structures try { m_pSndBuffer = new CSndBuffer((m_iMSS > 1500) ? 32 : 128, m_iPayloadSize); m_pRcvBuffer = new CRcvBuffer(m_iRcvBufSize, &(m_pRcvQueue->m_UnitQueue)); // after introducing lite ACK, the sndlosslist may not be cleared in time, so it requires twice space. m_pSndLossList = new CSndLossList(m_iFlowWindowSize * 2); m_pRcvLossList = new CRcvLossList(m_iFlightFlagSize); m_pACKWindow = new CACKWindow(4096); m_pRcvTimeWindow = new CPktTimeWindow(16, 64); m_pSndTimeWindow = new CPktTimeWindow(); } catch (...) { throw CUDTException(3, 2, 0); } m_pCC = m_pCCFactory->create(); m_pCC->m_UDT = m_SocketID; m_ullInterval = (uint64_t)(m_pCC->m_dPktSndPeriod * m_ullCPUFrequency); m_dCongestionWindow = m_pCC->m_dCWndSize; m_pController->join(this, serv_addr, m_iIPversion, m_iRTT, m_iBandwidth); m_pCC->setMSS(m_iMSS); m_pCC->setMaxCWndSize((int&)m_iFlowWindowSize); m_pCC->setSndCurrSeqNo(m_iSndCurrSeqNo); m_pCC->setRcvRate(m_iDeliveryRate); m_pCC->setRTT(m_iRTT); m_pCC->setBandwidth(m_iBandwidth); m_pCC->init(); m_pPeerAddr = (AF_INET == m_iIPversion) ? (sockaddr*)new sockaddr_in : (sockaddr*)new sockaddr_in6; memcpy(m_pPeerAddr, serv_addr, (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6)); // And, I am connected too. m_bConnected = true; // register this socket for receiving data packets m_pRcvQueue->setNewEntry(this);}void CUDT::connect(const sockaddr* peer, CHandShake* hs){ // Type 0 (handshake) control packet CPacket initpkt; CHandShake ci; memcpy(&ci, hs, sizeof(CHandShake)); initpkt.pack(0, NULL, &ci, sizeof(CHandShake)); // Uses the smaller MSS between the peers if (ci.m_iMSS > m_iMSS) ci.m_iMSS = m_iMSS; else m_iMSS = ci.m_iMSS; // exchange info for maximum flow window size m_iFlowWindowSize = ci.m_iFlightFlagSize; ci.m_iFlightFlagSize = (m_iRcvBufSize < m_iFlightFlagSize)? m_iRcvBufSize : m_iFlightFlagSize; m_iPeerISN = ci.m_iISN; m_iRcvLastAck = ci.m_iISN; m_iRcvLastAckAck = ci.m_iISN; m_iRcvCurrSeqNo = ci.m_iISN - 1; m_PeerID = ci.m_iID; ci.m_iID = m_SocketID; // use peer's ISN and send it back for security check m_iISN = ci.m_iISN; m_iLastDecSeq = m_iISN - 1; m_iSndLastAck = m_iISN; m_iSndLastDataAck = m_iISN; m_iSndCurrSeqNo = m_iISN - 1; // this is a reponse handshake ci.m_iReqType = -1; // Save the negotiated configurations. memcpy(hs, &ci, sizeof(CHandShake)); m_iPktSize = m_iMSS - 28; m_iPayloadSize = m_iPktSize - CPacket::m_iPktHdrSize; // Prepare all structures try { m_pSndBuffer = new CSndBuffer((m_iMSS > 1500) ? 32 : 128, m_iPayloadSize); m_pRcvBuffer = new CRcvBuffer(m_iRcvBufSize, &(m_pRcvQueue->m_UnitQueue)); m_pSndLossList = new CSndLossList(m_iFlowWindowSize * 2); m_pRcvLossList = new CRcvLossList(m_iFlightFlagSize); m_pACKWindow = new CACKWindow(4096); m_pRcvTimeWindow = new CPktTimeWindow(16, 64); m_pSndTimeWindow = new CPktTimeWindow(); } catch (...) { throw CUDTException(3, 2, 0); } m_pCC = m_pCCFactory->create(); m_pCC->m_UDT = m_SocketID; m_ullInterval = (uint64_t)(m_pCC->m_dPktSndPeriod * m_ullCPUFrequency); m_dCongestionWindow = m_pCC->m_dCWndSize; m_pController->join(this, peer, m_iIPversion, m_iRTT, m_iBandwidth); m_pCC->setMSS(m_iMSS); m_pCC->setMaxCWndSize((int&)m_iFlowWindowSize); m_pCC->setSndCurrSeqNo(m_iSndCurrSeqNo); m_pCC->setRcvRate(m_iDeliveryRate); m_pCC->setRTT(m_iRTT); m_pCC->setBandwidth(m_iBandwidth); m_pCC->init(); m_pPeerAddr = (AF_INET == m_iIPversion) ? (sockaddr*)new sockaddr_in : (sockaddr*)new sockaddr_in6; memcpy(m_pPeerAddr, peer, (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6)); // And of course, it is connected. m_bConnected = true; // register this socket for receiving data packets m_pRcvQueue->setNewEntry(this);}void CUDT::close(){ if (!m_bOpened) return; if (!m_bConnected) m_bClosing = true; if (0 != m_Linger.l_onoff) { uint64_t entertime = CTimer::getTime(); while (!m_bBroken && m_bConnected && (m_pSndBuffer->getCurrBufSize() > 0) && (CTimer::getTime() - entertime < m_Linger.l_linger * 1000000ULL)) { #ifndef WIN32 timespec ts; ts.tv_sec = 0; ts.tv_nsec = 1000000; nanosleep(&ts, NULL); #else Sleep(1); #endif } } // remove this socket from the snd queue m_pSndQueue->m_pSndUList->remove(m_SocketID); CGuard cg(m_ConnectionLock); // Inform the threads handler to stop. m_bClosing = true; // Signal the sender and recver if they are waiting for data. releaseSynch(); if (m_bListening) { m_bListening = false; m_pRcvQueue->removeListener(this); } if (m_bConnected) { if (!m_bShutdown) sendCtrl(5); m_pCC->close(); m_pController->leave(this, m_iRTT, m_iBandwidth); m_bConnected = false; if (m_bRendezvous) m_pRcvQueue->m_pRendezvousQueue->remove(m_SocketID); } // waiting all send and recv calls to stop CGuard sendguard(m_SendLock); CGuard recvguard(m_RecvLock); // CLOSED. m_bOpened = false;}int CUDT::send(const char* data, const int& len){ if (UDT_DGRAM == m_iSockType) throw CUDTException(5, 10, 0); CGuard sendguard(m_SendLock); // throw an exception if not connected if (m_bBroken) throw CUDTException(2, 1, 0); else if (!m_bConnected) throw CUDTException(2, 2, 0); if (len <= 0) return 0; if (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize()) { if (!m_bSynSending) throw CUDTException(6, 1, 0); else { // wait here during a blocking sending #ifndef WIN32 pthread_mutex_lock(&m_SendBlockLock); if (m_iSndTimeOut < 0) { while (!m_bBroken && m_bConnected && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize())) pthread_cond_wait(&m_SendBlockCond, &m_SendBlockLock); } else { uint64_t exptime = CTimer::getTime() + m_iSndTimeOut * 1000ULL; timespec locktime; locktime.tv_sec = exptime / 1000000; locktime.tv_nsec = (exptime % 1000000) * 1000; pthread_cond_timedwait(&m_SendBlockCond, &m_SendBlockLock, &locktime); } pthread_mutex_unlock(&m_SendBlockLock); #else if (m_iSndTimeOut < 0) { while (!m_bBroken && m_bConnected && (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize())) WaitForSingleObject(m_SendBlockCond, INFINITE); } else WaitForSingleObject(m_SendBlockCond, DWORD(m_iSndTimeOut)); #endif // check the connection status if (m_bBroken) throw CUDTException(2, 1, 0); else if (!m_bConnected) throw CUDTException(2, 2, 0); } } if ((m_iSndTimeOut >= 0) || (m_iSndBufSize <= m_pSndBuffer->getCurrBufSize())) return 0; int size = (m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize; if (size > len) size = len; // insert the user buffer into the sening list m_pSndBuffer->addBuffer(data, size); // insert this socket to snd list if it is not on the list yet m_pSndQueue->m_pSndUList->update(m_SocketID, this, false); return size;}int CUDT::recv(char* data, const int& len){ if (UDT_DGRAM == m_iSockType) throw CUDTException(5, 10, 0); CGuard recvguard(m_RecvLock); // throw an exception if not connected if (!m_bConnected) throw CUDTException(2, 2, 0); else if (m_bBroken && (0 == m_pRcvBuffer->getRcvDataSize())) throw CUDTException(2, 1, 0); if (len <= 0) return 0; if (0 == m_pRcvBuffer->getRcvDataSize()) { if (!m_bSynRecving) throw CUDTException(6, 2, 0); else { #ifndef WIN32 pthread_mutex_lock(&m_RecvDataLock); if (m_iRcvTimeOut < 0) { while (!m_bBroken && m_bConnected && (0 == m_pRcvBuffer->getRcvDataSize())) pthread_cond_wait(&m_RecvDataCond, &m_RecvDataLock); } else { uint64_t exptime = CTimer::getTime() + m_iRcvTimeOut * 1000ULL; timespec locktime; locktime.tv_sec = exptime / 1000000; locktime.tv_nsec = (exptime % 1000000) * 1000; pthread_cond_timedwait(&m_RecvDataCond, &m_RecvDataLock, &locktime); } pthread_mutex_unlock(&m_RecvDataLock); #else if (m_iRcvTimeOut < 0) { while (!m_bBroken && m_bConnected && (0 == m_pRcvBuffer->getRcvDataSize())) WaitForSingleObject(m_RecvDataCond, INFINITE); } else WaitForSingleObject(m_RecvDataCond, DWORD(m_iRcvTimeOut)); #endif } } // throw an exception if not connected if (!m_bConnected) throw CUDTException(2, 2, 0); else if (m_bBroken && (0 == m_pRcvBuffer->getRcvDataSize())) throw CUDTException(2, 1, 0); return m_pRcvBuffer->readBuffer(data, len);}int CUDT::sendmsg(const char* data, const int& len, const int& msttl, const bool& inorder){ if (UDT_STREAM == m_iSockType) throw CUDTException(5, 9, 0); CGuard sendguard(m_SendLock); // throw an exception if not connected if (m_bBroken) throw CUDTException(2, 1, 0); else if (!m_bConnected) throw CUDTException(2, 2, 0); if (len <= 0) return 0; if (len > m_iSndBufSize * m_iPayloadSize) throw CUDTException(5, 12, 0); if ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len) { if (!m_bSynSending) throw CUDTException(6, 1, 0); else { // wait here during a blocking sending #ifndef WIN32 pthread_mutex_lock(&m_SendBlockLock); if (m_iSndTimeOut < 0) { while (!m_bBroken && m_bConnected && ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len)) pthread_cond_wait(&m_SendBlockCond, &m_SendBlockLock); } else { uint64_t exptime = CTimer::getTime() + m_iSndTimeOut * 1000ULL; timespec locktime; locktime.tv_sec = exptime / 1000000; locktime.tv_nsec = (exptime % 1000000) * 1000; pthread_cond_timedwait(&m_SendBlockCond, &m_SendBlockLock, &locktime); } pthread_mutex_unlock(&m_SendBlockLock); #else if (m_iSndTimeOut < 0) { while (!m_bBroken && m_bConnected && ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len)) WaitForSingleObject(m_SendBlockCond, INFINITE); } else WaitForSingleObject(m_SendBlockCond, DWORD(m_iSndTimeOut)); #endif // check the connection status if (m_bBroken) throw CUDTException(2, 1, 0); else if (!m_bConnected) throw CUDTException(2, 2, 0); } } if ((m_iSndTimeOut >= 0) && ((m_iSndBufSize - m_pSndBuffer->getCurrBufSize()) * m_iPayloadSize < len)) return 0; // insert the user buffer into the sening list m_pSndBuffer->addBuffer(data, len, msttl, inorder); // insert this socket to the snd list if it is not on the list yet m_pSndQueue->m_pSndUList->update(m_SocketID, this, false); return len; }int CUDT::recvmsg(char* data, const int& len){ if (UDT_STREAM == m_iSockType) throw CUDTException(5, 9, 0); CGuard recvguard(m_RecvLock); // throw an exception if not connected if (!m_bConnected) throw CUDTException(2, 2, 0); if (len <= 0) return 0; if (m_bBroken) { int res = m_pRcvBuffer->readMsg(data, len); if (0 == res) throw CUDTException(2, 1, 0); else return res; } if (!m_bSynRecving) { int res = m_pRcvBuffer->readMsg(data, len); if (0 == res) throw CUDTException(6, 2, 0); else return res; } int res = 0; bool timeout = false; do { #ifndef WIN32 pthread_mutex_lock(&m_RecvDataLock); if (m_iRcvTimeOut < 0) { while (!m_bBroken && m_bConnected && (0 == (res = m_pRcvBuffer->readMsg(data, len)))) pthread_cond_wait(&m_RecvDataCond, &m_RecvDataLock); } else { uint64_t exptime = CTimer::getTime() + m_iRcvTimeOut * 1000ULL; timespec locktime;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -