// Functionality: // Create a new UDT connection. // Parameters: // 0) [in] listen: the listening UDT socket; // 1) [in] peer: peer address. // 2) [in/out] hs: handshake information from peer side (in), negotiated value (out); // Returned value: // If the new connection is successfully created: 1 success, 0 already exist, -1 error. public int newConnection(UDTSOCKET listen, IPEndPoint peer, CHandShake hs) { UdtSocket ns = null; UdtSocket ls = locate(listen); if (null == ls) return -1; // if this connection has already been processed if (null != (ns = locate(listen, peer, hs.m_iID, hs.m_iISN))) { if (ns.m_pUDT.m_bBroken) { // last connection from the "peer" address has been broken ns.m_Status = UDTSTATUS.CLOSED; ns.m_TimeStamp = CClock.getTime(); lock (ls.m_AcceptLock) { ls.m_pQueuedSockets.Remove(ns.m_SocketID); ls.m_pAcceptSockets.Remove(ns.m_SocketID); } } else { // connection already exist, this is a repeated connection request // respond with existing HS information hs.m_iISN = ns.m_pUDT.m_iISN; hs.m_iMSS = ns.m_pUDT.m_iMSS; hs.m_iFlightFlagSize = ns.m_pUDT.m_iFlightFlagSize; hs.m_iReqType = -1; hs.m_iID = ns.m_SocketID; return 0; //except for this situation a new connection should be started } } // exceeding backlog, refuse the connection request if (ls.m_pQueuedSockets.size() >= ls.m_uiBackLog) return -1; try { ns = new UdtSocket(); ns.m_pUDT = new CUDT((ls.m_pUDT)); if (AddressFamily.InterNetwork == ls.m_iIPversion) { ns.m_pSelfAddr = new IPEndPoint(IPAddress.Any, 0); ns.m_pPeerAddr = peer; } else { ns.m_pSelfAddr = new IPEndPoint(IPAddress.IPv6Any, 0); ns.m_pPeerAddr = peer; } } catch (Exception e) { ns = null; return -1; } lock (m_IDLock) { ns.m_SocketID = --m_SocketID; } ns.m_ListenSocket = listen; ns.m_iIPversion = ls.m_iIPversion; ns.m_pUDT.m_SocketID = ns.m_SocketID; ns.m_PeerID = hs.m_iID; ns.m_iISN = hs.m_iISN; int error = 0; try { // bind to the same addr of listening socket ns.m_pUDT.open(); updateMux(ns.m_pUDT, ls); ns.m_pUDT.connect(peer, hs); } catch (Exception e) { error = 1; goto ERR_ROLLBACK; } ns.m_Status = UDTSTATUS.CONNECTED; // copy address information of local node ns.m_pUDT.m_pSndQueue.m_pChannel.getSockAddr(ns.m_pSelfAddr); CIPAddress.pton(ns.m_pSelfAddr, ns.m_pUDT.m_piSelfIP, ns.m_iIPversion); // protect the m_Sockets structure. lock (m_ControlLock) { try { m_Sockets[ns.m_SocketID] = ns; } catch (Exception e) { error = 2; } } lock (ls.m_AcceptLock) { try { ls.m_pQueuedSockets.insert(ns.m_SocketID); } catch (Exception e) { error = 3; } } CClock.triggerEvent(); ERR_ROLLBACK: if (error > 0) { ns.m_pUDT.close(); ns.m_Status = UDTSTATUS.CLOSED; ns.m_TimeStamp = CClock.getTime(); return -1; } // wake up a waiting accept() call m_AcceptCond.Set(); return 1; }
// 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); }