示例#1
0
        // 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;
        }
示例#2
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);
}