// Functionality:
// Connect to a UDT entity listening at address "peer", which has sent "hs" request.
// Parameters:
// 0) [in] peer: The address of the listening UDT entity.
// 1) [in/out] hs: The handshake information sent by the peer side (in), negotiated value (out).
// Returned value:
// None.
public void connect(IPAddress 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;
m_iSndLastAck2 = m_iISN;
m_ullSndLastAck2Time = CClock.getTime();
// this is a reponse handshake
ci.m_iReqType = -1;
// get local IP address and send the peer its IP address (because UDP cannot get local IP address)
memcpy(m_piSelfIP, ci.m_piPeerIP, 16);
CIPAddress.ntop(peer, ci.m_piPeerIP, m_iIPversion);
// 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(32, 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 (Exception e)
{
throw new CUDTException(3, 2, 0);
}
m_pCC = m_pCCFactory.create();
m_pCC.m_UDT = m_SocketID;
m_ullInterval = (long)(m_pCC.m_dPktSndPeriod * m_ullCPUFrequency);
m_dCongestionWindow = m_pCC.m_dCWndSize;
CInfoBlock ib;
if (m_pCache.lookup(peer, m_iIPversion, &ib) >= 0)
{
m_iRTT = ib.m_iRTT;
m_iBandwidth = ib.m_iBandwidth;
}
m_pCC.setMSS(m_iMSS);
m_pCC.setMaxCWndSize((int)m_iFlowWindowSize);
m_pCC.setSndCurrSeqNo((int)m_iSndCurrSeqNo);
m_pCC.setRcvRate(m_iDeliveryRate);
m_pCC.setRTT(m_iRTT);
m_pCC.setBandwidth(m_iBandwidth);
if (m_llMaxBW > 0) m_pCC.setUserParam((char*)&(m_llMaxBW), 8);
m_pCC.init();
m_pPeerAddr = peer;
//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);
}