Пример #1
0
      // 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);
}
Пример #2
0
   internal CRNode m_pRNode;                    // node information for UDT list used in rcv queue
#endregion

#region constructor and desctructor
        CUDT(CUDT ancestor)
{
   m_pSndBuffer = null;
   m_pRcvBuffer = null;
   m_pSndLossList = null;
   m_pRcvLossList = null;
   m_pACKWindow = null;
   m_pSndTimeWindow = null;
   m_pRcvTimeWindow = null;

   m_pSndQueue = null;
   m_pRcvQueue = null;
   m_pPeerAddr = null;
   m_pSNode = null;
   m_pRNode = null;

   // Initilize mutex and condition variables
   initSynch();

   // Default UDT configurations
   m_iMSS = ancestor.m_iMSS;
   m_bSynSending = ancestor.m_bSynSending;
   m_bSynRecving = ancestor.m_bSynRecving;
   m_iFlightFlagSize = ancestor.m_iFlightFlagSize;
   m_iSndBufSize = ancestor.m_iSndBufSize;
   m_iRcvBufSize = ancestor.m_iRcvBufSize;
   m_Linger = ancestor.m_Linger;
   m_iUDPSndBufSize = ancestor.m_iUDPSndBufSize;
   m_iUDPRcvBufSize = ancestor.m_iUDPRcvBufSize;
   m_iSockType = ancestor.m_iSockType;
   m_iIPversion = ancestor.m_iIPversion;
   m_bRendezvous = ancestor.m_bRendezvous;
   m_iSndTimeOut = ancestor.m_iSndTimeOut;
   m_iRcvTimeOut = ancestor.m_iRcvTimeOut;
   m_bReuseAddr = true;	// this must be true, because all accepted sockets shared the same port with the listener
   m_llMaxBW = ancestor.m_llMaxBW;

   m_pCCFactory = ancestor.m_pCCFactory.clone();
   m_pCC = null;
   m_pCache = ancestor.m_pCache;

   // Initial status
   m_bOpened = false;
   m_bListening = false;
   m_bConnected = false;
   m_bClosing = false;
   m_bShutdown = false;
   m_bBroken = false;
}
Пример #3
0
      // Functionality:
      //    Connect to a UDT entity listening at address "peer".
      // Parameters:
      //    0) [in] peer: The address of the listening UDT entity.
      // Returned value:
      //    None.

        public void connect(IPEndPoint serv_addr)
{
   CGuard cg = new CGuard(m_ConnectionLock);

   if (!m_bOpened)
      throw new CUDTException(5, 0, 0);

   if (m_bListening)
      throw new CUDTException(5, 2, 0);

   if (m_bConnected)
      throw new CUDTException(5, 2, 0);

   // register this socket in the rendezvous queue
   m_pRcvQueue.m_pRendezvousQueue.insert(m_SocketID, m_iIPversion, serv_addr);

   CPacket request;
   byte[] reqdata = new byte [m_iPayloadSize];
   CHandShake req = (CHandShake)reqdata;

   CPacket response;
   byte[] resdata = new byte [m_iPayloadSize];
   CHandShake res = (CHandShake)resdata;

   // This is my current configurations.
   req.m_iVersion = m_iVersion;
   req.m_iType = m_iSockType;
   req.m_iMSS = m_iMSS;
   req.m_iFlightFlagSize = (m_iRcvBufSize < m_iFlightFlagSize)? m_iRcvBufSize : m_iFlightFlagSize;
   req.m_iReqType = (!m_bRendezvous) ? 1 : 0;
   req.m_iID = m_SocketID;
   CIPAddress.ntop(serv_addr, req.m_piPeerIP, m_iIPversion);

   // Random Initial Sequence Number
   srand((int)CClock.getTime());
   m_iISN = req.m_iISN = (Int32)(CSeqNo.m_iMaxSeqNo * ((double)(rand()) / RAND_MAX));

   m_iLastDecSeq = req.m_iISN - 1;
   m_iSndLastAck = req.m_iISN;
   m_iSndLastDataAck = req.m_iISN;
   m_iSndCurrSeqNo = req.m_iISN - 1;
   m_iSndLastAck2 = req.m_iISN;
   m_ullSndLastAck2Time = CClock.getTime();

   // 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));

   Int64 timeo = 3000000;
   if (m_bRendezvous)
      timeo *= 10;
   Int64 entertime = CClock.getTime();
   CUDTException e = new CUDTException(0, 0);

   byte[] tmp = null;

   while (!m_bClosing)
   {
      m_pSndQueue.sendto(serv_addr, request);

      response.setLength(m_iPayloadSize);
      if (m_pRcvQueue.recvfrom(m_SocketID, response) > 0)
      {
         if (m_bRendezvous && ((0 == response.getFlag()) || (1 == response.getType())) && (null != tmp))
         {
            // a data packet or a keep-alive packet comes, which means the peer side is already connected
            // in this situation, a previously recorded response (tmp) will be used
            memcpy(resdata, tmp, sizeof(CHandShake));
            memcpy(m_piSelfIP, res.m_piPeerIP, 16);
            break;
         }

         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) || (0 == req.m_iReqType))
            {
               tmp = new char [m_iPayloadSize];
               memcpy(tmp, resdata, sizeof(CHandShake));

               req.m_iReqType = -1;
               request.m_iID = res.m_iID;
               response.setLength(-1);
            }
         }
         else
         {
            // set cookie
            if (1 == res.m_iReqType)
            {
               req.m_iReqType = -1;
               req.m_iCookie = res.m_iCookie;
               response.setLength(-1);
            }
         }
      }

      if (response.getLength() > 0)
      {
         memcpy(m_piSelfIP, res.m_piPeerIP, 16);
         break;
      }

      if (CClock.getTime() > entertime + timeo)
      {
         // timeout
         e = CUDTException(1, 1, 0);
         break;
      }
   }

   //delete [] tmp;
   //delete [] reqdata;

   if (e.getErrorCode() == 0)
   {
      if (m_bClosing)						// if the socket is closed before connection...
         e = new CUDTException(1);
      else if (1002 == res.m_iReqType)				// connection request rejected
         e = new CUDTException(1, 2, 0);
      else if ((!m_bRendezvous) && (m_iISN != res.m_iISN))	// secuity check
         e = new 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(32, 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 (Exception e)
   {
      throw new CUDTException(3, 2, 0);
   }

   m_pCC = m_pCCFactory.create();
   m_pCC.m_UDT = m_SocketID;
   m_ullInterval = (Int64)(m_pCC.m_dPktSndPeriod * m_ullCPUFrequency);
   m_dCongestionWindow = m_pCC.m_dCWndSize;

   CInfoBlock ib;
   if (m_pCache.lookup(serv_addr, 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 = serv_addr;
   //         m_pPeerAddr = (AddressFamily.InterNetwork == m_iIPversion) ? new IPEndPoint(IPAddress.Any,0) : new IPEndPoint(IPAddress.IPv6Any,0);
   //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);

   // remove from rendezvous queue
   m_pRcvQueue.m_pRendezvousQueue.remove(m_SocketID);
}