Пример #1
0
        // Functionality:
        //    Read the first (smallest) loss seq. no. in the list and remove it.
        // Parameters:
        //    None.
        // Returned value:
        //    The seq. no. or -1 if the list is empty.

        public Int32 getLostSeq()
        {
            if (0 == m_iLength)
                return -1;

            CGuard listguard = new CGuard(m_ListLock);

            if (0 == m_iLength)
                return -1;

            if (m_iLastInsertPos == m_iHead)
                m_iLastInsertPos = -1;

            // return the first loss seq. no.
            Int32 seqno = m_piData1[m_iHead];

            // head moves to the next node
            if (-1 == m_piData2[m_iHead])
            {
                //[3, -1] becomes [], and head moves to next node in the list
                m_piData1[m_iHead] = -1;
                m_iHead = m_piNext[m_iHead];
            }
            else
            {
                // shift to next node, e.g., [3, 7] becomes [], [4, 7]
                int loc = (m_iHead + 1) % m_iSize;

                m_piData1[loc] = CSeqNo.incseq(seqno);
                if (CSeqNo.seqcmp(m_piData2[m_iHead], m_piData1[loc]) > 0)
                    m_piData2[loc] = m_piData2[m_iHead];

                m_piData1[m_iHead] = -1;
                m_piData2[m_iHead] = -1;

                m_piNext[loc] = m_piNext[m_iHead];
                m_iHead = loc;
            }

            m_iLength--;

            return seqno;
        }
Пример #2
0
        // Functionality:
        //    initialize the UDT library.
        // Parameters:
        //    None.
        // Returned value:
        //    0 if success, otherwise -1 is returned.
        static CUDTUnited()
        {
            m_InitLock = new Mutex();
            CGuard gcinit = new CGuard(m_InitLock);

            //init CTimer.EventLock

            if (m_bGCStatus)
                return true;

            m_bClosing = false;
            m_GCStopLock = new Mutex();
            m_GCStopCond = new AutoResetEvent(false);
            DWORD ThreadID;
            m_GCThread = CreateThread(null, 0, garbageCollect, this, null, &ThreadID);

            m_bGCStatus = true;

            return 0;
        }
Пример #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);
}
Пример #4
0
        void updateMux(CUDT u, IPEndPoint addr, Socket udpsock)
        {
            CGuard cg = new CGuard(m_ControlLock);

            if ((u.m_bReuseAddr) && (null != addr))
            {
                //int port = (AF_INET == u.m_iIPversion) ? ntohs(((sockaddr_in*)addr).sin_port) : ntohs(((sockaddr_in6*)addr).sin6_port);
                int port = addr.Port;

                // find a reusable address
                //for (vector<CMultiplexer>::iterator i = m_vMultiplexer.begin(); i != m_vMultiplexer.end(); ++ i)
                foreach (CMultiplexer i in m_vMultiplexer)
                {
                    if ((i.m_iIPversion == u.m_iIPversion) && (i.m_iMSS == u.m_iMSS) && i.m_bReusable)
                    {
                        if (i.m_iPort == port)
                        {
                            // reuse the existing multiplexer
                            ++i.m_iRefCount;
                            u.m_pSndQueue = i.m_pSndQueue;
                            u.m_pRcvQueue = i.m_pRcvQueue;
                            return;
                        }
                    }
                }
            }

            // a new multiplexer is needed
            CMultiplexer m;
            m.m_iMSS = u.m_iMSS;
            m.m_iIPversion = u.m_iIPversion;
            m.m_iRefCount = 1;
            m.m_bReusable = u.m_bReuseAddr;

            m.m_pChannel = new CChannel(u.m_iIPversion);
            m.m_pChannel.setSndBufSize(u.m_iUDPSndBufSize);
            m.m_pChannel.setRcvBufSize(u.m_iUDPRcvBufSize);

            try
            {
                if (null != udpsock)
                    m.m_pChannel.open(udpsock);
                else
                    m.m_pChannel.open(addr);
            }
            catch (CUDTException e)
            {
                m.m_pChannel.close();
                //delete m.m_pChannel;
                throw e;
            }

            IPEndPoint sa = (AddressFamily.InterNetwork == u.m_iIPversion) ? new IPEndPoint(IPAddress.Any, 0) : new IPEndPoint(IPAddress.IPv6Any, 0);
            m.m_pChannel.getSockAddr(out sa);
            m.m_iPort = sa.Port;
            //         (AF_INET == u.m_iIPversion) ? ntohs(((sockaddr_in*)sa).sin_port) : ntohs(((sockaddr_in6*)sa).sin6_port);
            //if (AddressFamily.InterNetwork == u.m_iIPversion) 
            //    delete (sockaddr_in*)sa; 
            // else 
            //     delete (sockaddr_in6*)sa;

            m.m_pTimer = new CClock();

            m.m_pSndQueue = new CSndQueue(m.m_pChannel, m.m_pTimer);
            m.m_pRcvQueue = new CRcvQueue();
            m.m_pRcvQueue.init(32, u.m_iPayloadSize, m.m_iIPversion, 1024, m.m_pChannel, m.m_pTimer);

            m_vMultiplexer.insert(m_vMultiplexer.end(), m);

            u.m_pSndQueue = m.m_pSndQueue;
            u.m_pRcvQueue = m.m_pRcvQueue;
        }
Пример #5
0
        DWORD garbageCollect(Object p)
        {
            CUDTUnited self = (CUDTUnited)p;

            CGuard gcguard = new CGuard(self.m_GCStopLock);

            while (!self.m_bClosing)
            {
                self.checkBrokenSockets();

                self.checkTLSValue();

                //WaitForSingleObject(self.m_GCStopCond, 1000);
                self.m_GCStopCond.WaitOne(1000);
            }

            // remove all sockets and multiplexers
            foreach (KeyValuePair<UDTSOCKET, UdtSocket> kvp in m_Sockets)
            {
                kvp.Value.m_pUDT.close();
                kvp.Value.m_Status = UDTSTATUS.CLOSED;
                kvp.Value.m_TimeStamp = CClock.getTime();
                self.m_ClosedSockets[kvp.Key] = kvp.Value;
            }
            self.m_Sockets.Clear();

            while (self.m_ClosedSockets.Count > 0)
            {
                Thread.Sleep(1);

                self.checkBrokenSockets();
            }

            return 0;
        }
Пример #6
0
 public void setNewEntry(CUDT u)
 {
     CGuard listguard = new CGuard(m_IDLock);
     m_vNewEntry.insert(m_vNewEntry.end(), u);
 }
Пример #7
0
        // Functionality:
        //    look up the most recent UDT exception.
        // Parameters:
        //    None.
        // Returned value:
        //    pointer to a UDT exception instance.

        public CUDTException getError()
        {
            CGuard tg = new CGuard(m_TLSLock);
            if (null == TlsGetValue(m_TLSError))
            {
                CUDTException* e = new CUDTException();
                TlsSetValue(m_TLSError, e);
                m_mTLSRecord[GetCurrentThreadId()] = e;
            }
            return (CUDTException*)TlsGetValue(m_TLSError);
        }
Пример #8
0
      // Functionality:
      //    Request UDT to receive data into a file described as "fd", starting from "offset", with expected size of "size".
      // Parameters:
      //    0) [out] ofs: The output file stream.
      //    1) [in] offset: From where to write data;
      //    2) [in] size: How many data to be received.
      //    3) [in] block: size of block per write to disk
      // Returned value:
      //    Actual size of data received.

public Int64 recvfile(Stream ofs, Int64 offset, Int64 size, int block)
{
   if (UDT_DGRAM == m_iSockType)
      throw new CUDTException(5, 10, 0);

   if (!m_bConnected)
      throw new CUDTException(2, 2, 0);
   else if ((m_bBroken || m_bClosing) && (0 == m_pRcvBuffer.getRcvDataSize()))
      throw new CUDTException(2, 1, 0);

   if (size <= 0)
      return 0;

   CGuard recvguard = new CGuard(m_RecvLock);

   long torecv = size;
   int unitsize = block;
   int recvsize;

   // positioning...
   try
   {
      ofs.seekp((streamoff)offset);
   }
   catch (Exception e)
   {
      throw new CUDTException(4, 3);
   }

   // receiving... "recvfile" is always blocking
   while (torecv > 0)
   {
      if (ofs.bad() || ofs.fail())
         break;

         while (!m_bBroken && m_bConnected && !m_bClosing && (0 == m_pRcvBuffer.getRcvDataSize()))
             m_RecvDataCond.WaitOne(-1);

      if (!m_bConnected)
         throw new CUDTException(2, 2, 0);
      else if ((m_bBroken || m_bClosing) && (0 == m_pRcvBuffer.getRcvDataSize()))
         throw new CUDTException(2, 1, 0);

      unitsize = (int)((torecv >= block) ? block : torecv);
      recvsize = m_pRcvBuffer.readBufferToFile(ofs, unitsize);

      torecv -= recvsize;
   }

   return size - torecv;
}
Пример #9
0
      // Functionality:
      //    Configure UDT options.
      // Parameters:
      //    0) [in] optName: The enum name of a UDT option.
      //    1) [in] optval: The value to be set.
      //    2) [in] optlen: size of "optval".
      // Returned value:
      //    None.

void setOpt(UDTOpt optName, Object optval, int optlen)
{
   CGuard cg = new CGuard(m_ConnectionLock);
   CGuard sendguard = new CGuard(m_SendLock);
   CGuard recvguard = new CGuard(m_RecvLock);

   switch (optName)
   {
   case UDTOpt.UDT_MSS:
      if (m_bOpened)
         throw new CUDTException(5, 1, 0);

      if ((int)optval < (int)(28 + sizeof(CHandShake)))
         throw new CUDTException(5, 3, 0);

      m_iMSS = (int)optval;

      // Packet size cannot be greater than UDP buffer size
      if (m_iMSS > m_iUDPSndBufSize)
         m_iMSS = m_iUDPSndBufSize;
      if (m_iMSS > m_iUDPRcvBufSize)
         m_iMSS = m_iUDPRcvBufSize;

      break;

   case UDTOpt.UDT_SNDSYN:
      m_bSynSending = (bool)optval;
      break;

   case UDTOpt.UDT_RCVSYN:
      m_bSynRecving = (bool)optval;
      break;

   case UDTOpt.UDT_CC:
      if (m_bConnected)
         throw new CUDTException(5, 1, 0);
      //if (null != m_pCCFactory)
      //   delete m_pCCFactory;
      m_pCCFactory = ((CCCVirtualFactory )optval).clone();

      break;

   case UDTOpt.UDT_FC:
      if (m_bConnected)
         throw new CUDTException(5, 2, 0);

      if (*(int*)optval < 1)
         throw new CUDTException(5, 3);

      // Mimimum recv flight flag size is 32 packets
      if (*(int*)optval > 32)
         m_iFlightFlagSize = *(int*)optval;
      else
         m_iFlightFlagSize = 32;

      break;

   case UDTOpt.UDT_SNDBUF:
      if (m_bOpened)
         throw new CUDTException(5, 1, 0);

      if (*(int*)optval <= 0)
         throw new CUDTException(5, 3, 0);

      m_iSndBufSize = *(int*)optval / (m_iMSS - 28);

      break;

   case UDTOpt.UDT_RCVBUF:
      if (m_bOpened)
         throw new CUDTException(5, 1, 0);

      if (*(int*)optval <= 0)
         throw new CUDTException(5, 3, 0);

      // Mimimum recv buffer size is 32 packets
      if (*(int*)optval > (m_iMSS - 28) * 32)
         m_iRcvBufSize = *(int*)optval / (m_iMSS - 28);
      else
         m_iRcvBufSize = 32;

      // recv buffer MUST not be greater than FC size
      if (m_iRcvBufSize > m_iFlightFlagSize)
         m_iRcvBufSize = m_iFlightFlagSize;

      break;

   case UDTOpt.UDT_LINGER:
      m_Linger = *(linger*)optval;
      break;

   case UDTOpt.UDP_SNDBUF:
      if (m_bOpened)
         throw new CUDTException(5, 1, 0);

      m_iUDPSndBufSize = *(int*)optval;

      if (m_iUDPSndBufSize < m_iMSS)
         m_iUDPSndBufSize = m_iMSS;

      break;

   case UDTOpt.UDP_RCVBUF:
      if (m_bOpened)
         throw new CUDTException(5, 1, 0);

      m_iUDPRcvBufSize = *(int*)optval;

      if (m_iUDPRcvBufSize < m_iMSS)
         m_iUDPRcvBufSize = m_iMSS;

      break;

   case UDTOpt.UDT_RENDEZVOUS:
      if (m_bConnected)
         throw new CUDTException(5, 1, 0);
      m_bRendezvous = *(bool *)optval;
      break;

   case UDTOpt.UDT_SNDTIMEO: 
      m_iSndTimeOut = *(int*)optval; 
      break; 
    
   case UDTOpt.UDT_RCVTIMEO: 
      m_iRcvTimeOut = *(int*)optval; 
      break; 

   case UDTOpt.UDT_REUSEADDR:
      if (m_bOpened)
         throw new CUDTException(5, 1, 0);
      m_bReuseAddr = *(bool*)optval;
      break;

   case UDTOpt.UDT_MAXBW:
      if (m_bConnected)
         throw new CUDTException(5, 1, 0);
      m_llMaxBW = *(Int64*)optval;
      break;
    
   default:
      throw new CUDTException(5, 0, 0);
   }
}
Пример #10
0
      // Functionality:
      //    Receive a message to buffer "data".
      // Parameters:
      //    0) [out] data: data received.
      //    1) [in] len: size of the buffer.
      // Returned value:
      //    Actual size of data received.

        public int recvmsg(byte[] data, int len)
{
   if (UDT_STREAM == m_iSockType)
      throw new CUDTException(5, 9, 0);

   // throw an exception if not connected
   if (!m_bConnected)
      throw new CUDTException(2, 2, 0);

   if (len <= 0)
      return 0;

   CGuard recvguard = new CGuard(m_RecvLock);

   if (m_bBroken || m_bClosing)
   {
      int res = m_pRcvBuffer.readMsg(data, len);
      if (0 == res)
         throw new CUDTException(2, 1, 0);
      else
         return res;
   }

   if (!m_bSynRecving)
   {
      int res = m_pRcvBuffer.readMsg(data, len);
      if (0 == res)
         throw new CUDTException(6, 2, 0);
      else
         return res;
   }

   int res = 0;
   bool timeout = false;

   do
   {

         if (m_iRcvTimeOut < 0)
         {
            while (!m_bBroken && m_bConnected && !m_bClosing && (0 == (res = m_pRcvBuffer.readMsg(data, len))))
               WaitForSingleObject(m_RecvDataCond, INFINITE);
         }
         else
         {
            if (WaitForSingleObject(m_RecvDataCond, DWORD(m_iRcvTimeOut)) == WAIT_TIMEOUT)
               timeout = true;

            res = m_pRcvBuffer.readMsg(data, len);
         }

      if (m_bBroken || m_bClosing)
         throw new CUDTException(2, 1, 0);
      else if (!m_bConnected)
         throw new CUDTException(2, 2, 0);
   } while ((0 == res) && !timeout);

   return res;
}
Пример #11
0
      // Functionality:
      //    Request UDT to send out a file described as "fd", starting from "offset", with size of "size".
      // Parameters:
      //    0) [in] ifs: The input file stream.
      //    1) [in] offset: From where to read and send data;
      //    2) [in] size: How many data to be sent.
      //    3) [in] block: size of block per read from disk
      // Returned value:
      //    Actual size of data sent.

        public Int64 sendfile(Stream ifs, Int64 offset, Int64 size, int block)
{
   if (UDT_DGRAM == m_iSockType)
      throw new CUDTException(5, 10, 0);

   if (m_bBroken || m_bClosing)
      throw new CUDTException(2, 1, 0);
   else if (!m_bConnected)
      throw new CUDTException(2, 2, 0);

   if (size <= 0)
      return 0;

   CGuard sendguard = new CGuard(m_SendLock);

   long tosend = size;
   int unitsize;

   // positioning...
   try
   {
      ifs.seekg((streamoff)offset);
   }
   catch (Exception e)
   {
      throw new CUDTException(4, 1);
   }

   // sending block by block
   while (tosend > 0)
   {
      if (ifs.bad() || ifs.fail() || ifs.eof())
         break;

      unitsize = (int)((tosend >= block) ? block : tosend);

         while (!m_bBroken && m_bConnected && !m_bClosing && (m_iSndBufSize <= m_pSndBuffer.getCurrBufSize()))
            WaitForSingleObject(m_SendBlockCond, INFINITE);

      if (m_bBroken || m_bClosing)
         throw new CUDTException(2, 1, 0);
      else if (!m_bConnected)
         throw new CUDTException(2, 2, 0);

      // record total time used for sending
      if (0 == m_pSndBuffer.getCurrBufSize())
         m_llSndDurationCounter = CClock.getTime();

      tosend -= m_pSndBuffer.addBufferFromFile(ifs, unitsize);

      // insert this socket to snd list if it is not on the list yet
      m_pSndQueue.m_pSndUList.update(this, false);
   }

   return size - tosend;
}
Пример #12
0
      // Functionality:
      //    send a message of a memory block "data" with size of "len".
      // Parameters:
      //    0) [out] data: data received.
      //    1) [in] len: The desired size of data to be received.
      //    2) [in] ttl: the time-to-live of the message.
      //    3) [in] inorder: if the message should be delivered in order.
      // Returned value:
      //    Actual size of data sent.

public        int sendmsg(byte[] data, int len, int msttl, bool inorder)
{
   if (UDT_STREAM == m_iSockType)
      throw new CUDTException(5, 9, 0);

   // throw an exception if not connected
   if (m_bBroken || m_bClosing)
      throw new CUDTException(2, 1, 0);
   else if (!m_bConnected)
      throw new CUDTException(2, 2, 0);

   if (len <= 0)
      return 0;

   if (len > m_iSndBufSize * m_iPayloadSize)
      throw new CUDTException(5, 12, 0);

   CGuard sendguard = new CGuard(m_SendLock);

   if ((m_iSndBufSize - m_pSndBuffer.getCurrBufSize()) * m_iPayloadSize < len)
   {
      if (!m_bSynSending)
         throw new CUDTException(6, 1, 0);
      else
      {
         // wait here during a blocking sending

            if (m_iSndTimeOut < 0)
            {
               while (!m_bBroken && m_bConnected && !m_bClosing && ((m_iSndBufSize - m_pSndBuffer.getCurrBufSize()) * m_iPayloadSize < len))
                  WaitForSingleObject(m_SendBlockCond, INFINITE);
            }
            else
               WaitForSingleObject(m_SendBlockCond, DWORD(m_iSndTimeOut));

         // check the connection status
         if (m_bBroken || m_bClosing)
            throw new CUDTException(2, 1, 0);
         else if (!m_bConnected)
            throw new CUDTException(2, 2, 0);
      }
   }

   if ((m_iSndBufSize - m_pSndBuffer.getCurrBufSize()) * m_iPayloadSize < len)
      return 0;

   // record total time used for sending
   if (0 == m_pSndBuffer.getCurrBufSize())
      m_llSndDurationCounter = CClock.getTime();

   // 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(this, false);

   return len;   
}
Пример #13
0
      // Functionality:
      //    Request UDT to receive data to a memory block "data" with size of "len".
      // Parameters:
      //    0) [out] data: data received.
      //    1) [in] len: The desired size of data to be received.
      // Returned value:
      //    Actual size of data received.

public int recv(byte[] data, int len)
{
   if (UDT_DGRAM == m_iSockType)
      throw new CUDTException(5, 10, 0);

   // throw an exception if not connected
   if (!m_bConnected)
      throw new CUDTException(2, 2, 0);
   else if ((m_bBroken || m_bClosing) && (0 == m_pRcvBuffer.getRcvDataSize()))
      throw new CUDTException(2, 1, 0);

   if (len <= 0)
      return 0;

   CGuard recvguard = new CGuard(m_RecvLock);

   if (0 == m_pRcvBuffer.getRcvDataSize())
   {
      if (!m_bSynRecving)
         throw new CUDTException(6, 2, 0);
      else
      {

            if (m_iRcvTimeOut < 0)
            {
               while (!m_bBroken && m_bConnected && !m_bClosing && (0 == m_pRcvBuffer.getRcvDataSize()))
                  WaitForSingleObject(m_RecvDataCond, INFINITE);
            }
            else
            {
               Int64 enter_time = CClock.getTime();

               while (!m_bBroken && m_bConnected && !m_bClosing && (0 == m_pRcvBuffer.getRcvDataSize()))
               {
                  int diff = (int)(CClock.getTime() - enter_time) / 1000;
                  if (diff >= m_iRcvTimeOut)
                      break;
                  WaitForSingleObject(m_RecvDataCond, DWORD(m_iRcvTimeOut - diff ));
               }
            }
      }
   }

   // throw an exception if not connected
   if (!m_bConnected)
      throw new CUDTException(2, 2, 0);
   else if ((m_bBroken || m_bClosing) && (0 == m_pRcvBuffer.getRcvDataSize()))
      throw new CUDTException(2, 1, 0);

   return m_pRcvBuffer.readBuffer(data, len);
}
Пример #14
0
      // Functionality:
      //    Close the opened UDT entity.
      // Parameters:
      //    None.
      // Returned value:
      //    None.

public void close()
{
   if (!m_bOpened)
      return;

   if (!m_bConnected)
      m_bClosing = true;

   if (0 != m_Linger.l_onoff)
   {
      Int64 entertime = CClock.getTime();

      while (!m_bBroken && m_bConnected && (m_pSndBuffer.getCurrBufSize() > 0) && (CClock.getTime() - entertime < m_Linger.l_linger * 1000000))
      {
            Thread.Sleep(1);
      }
   }

   // remove this socket from the snd queue
   if (m_bConnected)
      m_pSndQueue.m_pSndUList.remove(this);

   CGuard cg = new CGuard(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();

      CInfoBlock ib;
      ib.m_iRTT = m_iRTT;
      ib.m_iBandwidth = m_iBandwidth;
      m_pCache.update(m_pPeerAddr, m_iIPversion, &ib);

      m_bConnected = false;
   }

   // waiting all send and recv calls to stop
   CGuard sendguard = new CGuard(m_SendLock);
   CGuard recvguard = new CGuard(m_RecvLock);

   // CLOSED.
   m_bOpened = false;
}
Пример #15
0
        //~CSndLossList()
        //{
        //    m_ListLock.Close();
        //}

        // Functionality:
        //    Insert a seq. no. into the sender loss list.
        // Parameters:
        //    0) [in] seqno1: sequence number starts.
        //    1) [in] seqno2: sequence number ends.
        // Returned value:
        //    number of packets that are not in the list previously.

        public override int insert(Int32 seqno1, Int32 seqno2)
        {
            CGuard listguard = new CGuard(m_ListLock);

            if (0 == m_iLength)
            {
                // insert data into an empty list

                m_iHead = 0;
                m_piData1[m_iHead] = seqno1;
                if (seqno2 != seqno1)
                    m_piData2[m_iHead] = seqno2;

                m_piNext[m_iHead] = -1;
                m_iLastInsertPos = m_iHead;

                m_iLength += CSeqNo.seqlen(seqno1, seqno2);

                return m_iLength;
            }

            // otherwise find the position where the data can be inserted
            int origlen = m_iLength;
            int offset = CSeqNo.seqoff(m_piData1[m_iHead], seqno1);
            int loc = (m_iHead + offset + m_iSize) % m_iSize;

            if (offset < 0)
            {
                // Insert data prior to the head pointer

                m_piData1[loc] = seqno1;
                if (seqno2 != seqno1)
                    m_piData2[loc] = seqno2;

                // new node becomes head
                m_piNext[loc] = m_iHead;
                m_iHead = loc;
                m_iLastInsertPos = loc;

                m_iLength += CSeqNo.seqlen(seqno1, seqno2);
            }
            else if (offset > 0)
            {
                if (seqno1 == m_piData1[loc])
                {
                    m_iLastInsertPos = loc;

                    // first seqno is equivlent, compare the second
                    if (-1 == m_piData2[loc])
                    {
                        if (seqno2 != seqno1)
                        {
                            m_iLength += CSeqNo.seqlen(seqno1, seqno2) - 1;
                            m_piData2[loc] = seqno2;
                        }
                    }
                    else if (CSeqNo.seqcmp(seqno2, m_piData2[loc]) > 0)
                    {
                        // new seq pair is longer than old pair, e.g., insert [3, 7] to [3, 5], becomes [3, 7]
                        m_iLength += CSeqNo.seqlen(m_piData2[loc], seqno2) - 1;
                        m_piData2[loc] = seqno2;
                    }
                    else
                        // Do nothing if it is already there
                        return 0;
                }
                else
                {
                    // searching the prior node
                    int i;
                    if ((-1 != m_iLastInsertPos) && (CSeqNo.seqcmp(m_piData1[m_iLastInsertPos], seqno1) < 0))
                        i = m_iLastInsertPos;
                    else
                        i = m_iHead;

                    while ((-1 != m_piNext[i]) && (CSeqNo.seqcmp(m_piData1[m_piNext[i]], seqno1) < 0))
                        i = m_piNext[i];

                    if ((-1 == m_piData2[i]) || (CSeqNo.seqcmp(m_piData2[i], seqno1) < 0))
                    {
                        m_iLastInsertPos = loc;

                        // no overlap, create new node
                        m_piData1[loc] = seqno1;
                        if (seqno2 != seqno1)
                            m_piData2[loc] = seqno2;

                        m_piNext[loc] = m_piNext[i];
                        m_piNext[i] = loc;

                        m_iLength += CSeqNo.seqlen(seqno1, seqno2);
                    }
                    else
                    {
                        m_iLastInsertPos = i;

                        // overlap, coalesce with prior node, insert(3, 7) to [2, 5], ... becomes [2, 7]
                        if (CSeqNo.seqcmp(m_piData2[i], seqno2) < 0)
                        {
                            m_iLength += CSeqNo.seqlen(m_piData2[i], seqno2) - 1;
                            m_piData2[i] = seqno2;

                            loc = i;
                        }
                        else
                            return 0;
                    }
                }
            }
            else
            {
                m_iLastInsertPos = m_iHead;

                // insert to head node
                if (seqno2 != seqno1)
                {
                    if (-1 == m_piData2[loc])
                    {
                        m_iLength += CSeqNo.seqlen(seqno1, seqno2) - 1;
                        m_piData2[loc] = seqno2;
                    }
                    else if (CSeqNo.seqcmp(seqno2, m_piData2[loc]) > 0)
                    {
                        m_iLength += CSeqNo.seqlen(m_piData2[loc], seqno2) - 1;
                        m_piData2[loc] = seqno2;
                    }
                    else
                        return 0;
                }
                else
                    return 0;
            }

            // coalesce with next node. E.g., [3, 7], ..., [6, 9] becomes [3, 9] 
            while ((-1 != m_piNext[loc]) && (-1 != m_piData2[loc]))
            {
                int i = m_piNext[loc];

                if (CSeqNo.seqcmp(m_piData1[i], CSeqNo.incseq(m_piData2[loc])) <= 0)
                {
                    // coalesce if there is overlap
                    if (-1 != m_piData2[i])
                    {
                        if (CSeqNo.seqcmp(m_piData2[i], m_piData2[loc]) > 0)
                        {
                            if (CSeqNo.seqcmp(m_piData2[loc], m_piData1[i]) >= 0)
                                m_iLength -= CSeqNo.seqlen(m_piData1[i], m_piData2[loc]);

                            m_piData2[loc] = m_piData2[i];
                        }
                        else
                            m_iLength -= CSeqNo.seqlen(m_piData1[i], m_piData2[i]);
                    }
                    else
                    {
                        if (m_piData1[i] == CSeqNo.incseq(m_piData2[loc]))
                            m_piData2[loc] = m_piData1[i];
                        else
                            m_iLength--;
                    }

                    m_piData1[i] = -1;
                    m_piData2[i] = -1;
                    m_piNext[loc] = m_piNext[i];
                }
                else
                    break;
            }

            return m_iLength - origlen;
        }
Пример #16
0
      // Functionality:
      //    Read UDT options.
      // Parameters:
      //    0) [in] optName: The enum name of a UDT option.
      //    1) [in] optval: The value to be returned.
      //    2) [out] optlen: size of "optval".
      // Returned value:
      //    None.

void getOpt(UDTOpt optName, Object optval, int optlen)
{
   CGuard cg = new CGuard(m_ConnectionLock);

   switch (optName)
   {
   case UDT_MSS:
      *(int*)optval = m_iMSS;
      optlen = sizeof(int);
      break;

   case UDT_SNDSYN:
      *(bool*)optval = m_bSynSending;
      optlen = sizeof(bool);
      break;

   case UDT_RCVSYN:
      *(bool*)optval = m_bSynRecving;
      optlen = sizeof(bool);
      break;

   case UDT_CC:
      if (!m_bOpened)
         throw new CUDTException(5, 5, 0);
      *(CCC**)optval = m_pCC;
      optlen = sizeof(CCC*);

      break;

   case UDT_FC:
      *(int*)optval = m_iFlightFlagSize;
      optlen = sizeof(int);
      break;

   case UDT_SNDBUF:
      *(int*)optval = m_iSndBufSize * (m_iMSS - 28);
      optlen = sizeof(int);
      break;

   case UDT_RCVBUF:
      *(int*)optval = m_iRcvBufSize * (m_iMSS - 28);
      optlen = sizeof(int);
      break;

   case UDT_LINGER:
      if (optlen < (int)(sizeof(linger)))
         throw new CUDTException(5, 3, 0);

      *(linger*)optval = m_Linger;
      optlen = sizeof(linger);
      break;

   case UDP_SNDBUF:
      *(int*)optval = m_iUDPSndBufSize;
      optlen = sizeof(int);
      break;

   case UDP_RCVBUF:
      *(int*)optval = m_iUDPRcvBufSize;
      optlen = sizeof(int);
      break;

   case UDT_RENDEZVOUS:
      *(bool *)optval = m_bRendezvous;
      optlen = sizeof(bool);
      break;

   case UDT_SNDTIMEO: 
      *(int*)optval = m_iSndTimeOut; 
      optlen = sizeof(int); 
      break; 
    
   case UDT_RCVTIMEO: 
      *(int*)optval = m_iRcvTimeOut; 
      optlen = sizeof(int); 
      break; 

   case UDT_REUSEADDR:
      *(bool *)optval = m_bReuseAddr;
      optlen = sizeof(bool);
      break;

   case UDT_MAXBW:
      *(Int64*)optval = m_llMaxBW;
      break;

   default:
      throw new CUDTException(5, 0, 0);
   }
}
Пример #17
0
        // Functionality:
        //    Read a packet for a specific UDT socket id.
        // Parameters:
        //    1) [in] id: Socket ID
        //    2) [out] packet: received packet
        // Returned value:
        //    Data size of the packet

        public int recvfrom(int id, ref CPacket packet)
        {
            packet = null;

            CGuard bufferlock = new CGuard(m_PassLock);

            // Try to find a packet for the specified
            // socket ID
            CPacket workPacket;
            if (!m_mBuffer.TryGetValue(id, out workPacket))
            {
                // If we didn't find the packet waiting already
                // Then wait around until a packet arrives
                m_PassLock.ReleaseMutex();
                m_PassCond.WaitOne(1000);
                m_PassLock.WaitOne(-1);

                // Try to find it again
                if (!m_Buffer.TryGetValue(id, out workPacket))
                {
                    packet.setLength(-1);
                    return -1;
                }
            }

            if (packet.getLength() < i.second.getLength())
            {
                packet.setLength(-1);
                return -1;
            }

            workPacket.m_nHeader.CopyTo(packet.m_nHeader, 0);
            workPacket.m_pcData.CopyTo(packet.m_pcData, 0);
            packet.setLength(workPacket.getLength());

            m_mBuffer.Remove(i);

            return packet.getLength();
        }
Пример #18
0
private int CUDTpackData(CPacket packet, Int64 ts)
{
   int payload = 0;
   bool probe = false;

   Int64 entertime;
   CClock.rdtsc(out entertime);

   if ((0 != m_ullTargetTime) && (entertime > m_ullTargetTime))
      m_ullTimeDiff += entertime - m_ullTargetTime;

   // Loss retransmission always has higher priority.
   if ((packet.m_iSeqNo = m_pSndLossList.getLostSeq()) >= 0)
   {
      // protect m_iSndLastDataAck from updating by ACK processing
      CGuard ackguard = new CGuard(m_AckLock);

      int offset = CSeqNo.seqoff((Int32)m_iSndLastDataAck, packet.m_iSeqNo);
      if (offset < 0)
         return 0;

      int msglen;

      payload = m_pSndBuffer.readData(&(packet.m_pcData), offset, packet.m_iMsgNo, msglen);

      if (-1 == payload)
      {
         Int32[] seqpair = new int[2];
         seqpair[0] = packet.m_iSeqNo;
         seqpair[1] = CSeqNo.incseq(seqpair[0], msglen);
         sendCtrl(7, &packet.m_iMsgNo, seqpair, 8);

         // only one msg drop request is necessary
         m_pSndLossList.remove(seqpair[1]);

         return 0;
      }
      else if (0 == payload)
         return 0;

      ++ m_iTraceRetrans;
      ++ m_iRetransTotal;
   }
   else
   {
      // If no loss, pack a new packet.

      // check congestion/flow window limit
      int cwnd = (m_iFlowWindowSize < (int)m_dCongestionWindow) ? m_iFlowWindowSize : (int)m_dCongestionWindow;
      if (cwnd >= CSeqNo.seqlen((m_iSndLastAck), CSeqNo.incseq(m_iSndCurrSeqNo)))
      {
         if (0 != (payload = m_pSndBuffer.readData(&(packet.m_pcData), packet.m_iMsgNo)))
         {
            m_iSndCurrSeqNo = CSeqNo.incseq(m_iSndCurrSeqNo);
            m_pCC.setSndCurrSeqNo((Int32)m_iSndCurrSeqNo);

            packet.m_iSeqNo = m_iSndCurrSeqNo;

            // every 16 (0xF) packets, a packet pair is sent
            if (0 == (packet.m_iSeqNo & 0xF))
               probe = true;
         }
         else
         {
            m_ullTargetTime = 0;
            m_ullTimeDiff = 0;
            ts = 0;
            return 0;
         }
      }
      else
      {
         m_ullTargetTime = 0;
         m_ullTimeDiff = 0;
         ts = 0;
         return 0;
      }
   }

   packet.m_iTimeStamp = (int)(CClock.getTime() - m_StartTime);
   m_pSndTimeWindow.onPktSent(packet.m_iTimeStamp);

   packet.m_iID = m_PeerID;

   m_pCC.onPktSent(&packet);

   ++ m_llTraceSent;
   ++ m_llSentTotal;

   if (probe)
   {
      // sends out probing packet pair
      ts = entertime;
      probe = false;
   }
   else
   {
         if (m_ullTimeDiff >= m_ullInterval)
         {
            ts = entertime;
            m_ullTimeDiff -= m_ullInterval;
         }
         else
         {
            ts = entertime + m_ullInterval - m_ullTimeDiff;
            m_ullTimeDiff = 0;
         }
   }

   m_ullTargetTime = ts;

   packet.m_iID = m_PeerID;
   packet.setLength(payload);

   return payload;
}
Пример #19
0
        // Functionality:
        //    record the UDT exception.
        // Parameters:
        //    0) [in] e: pointer to a UDT exception instance.
        // Returned value:
        //    None.

        internal void setError(CUDTException e)
        {
            CGuard tg = new CGuard(m_TLSLock);
            //delete (CUDTException*)TlsGetValue(m_TLSError);
            //TlsSetValue(m_TLSError, e);
            m_mTLSRecord[GetCurrentThreadId()] = e;
        }
Пример #20
0
public static int listen(IPAddress addr, out CPacket packet)
{
   CGuard cg = new CGuard(m_ConnectionLock);
   if (m_bClosing)
      return 1002;

   CHandShake hs = (CHandShake )packet.m_pcData;

   // SYN cookie
   byte[] clienthost = new byte[NI_MAXHOST];
   byte[] clientport = new byte[NI_MAXSERV];
   getnameinfo(addr, (AF_INET == m_iVersion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6), clienthost, sizeof(clienthost), clientport, sizeof(clientport), NI_NUMERICHOST|NI_NUMERICSERV);
   Int64 timestamp = (CClock.getTime() - m_StartTime) / 60000000; // secret changes every one minute
   //byte[] cookiestr = new byte[1024];
   //sprintf(cookiestr, "%s:%s:%lld", clienthost, clientport, (long long int)timestamp);
    
    string cookiestr = string.Format("{0}:{1}:{2}", clienthost, clientport, timestamp);
   byte[] cookie = new byte[16];
   CMD5.compute(cookiestr, cookie);

   if (1 == hs.m_iReqType)
   {
      hs.m_iCookie = *(int*)cookie;
      packet.m_iID = hs.m_iID;
      m_pSndQueue.sendto(addr, packet);

      return 0;
   }
   else
   {
      if (hs.m_iCookie != *(int*)cookie)
      {
         timestamp --;
         cookiestr = string.Format("{0}:{1}:{2}", clienthost, clientport, timestamp);
         CMD5.compute(cookiestr, out cookie);

         if (hs.m_iCookie != *(int*)cookie)
            return -1;
      }
   }

   Int32 id = hs.m_iID;

   // When a peer side connects in...
   if ((1 == packet.getFlag()) && (0 == packet.getType()))
   {
      if ((hs.m_iVersion != m_iVersion) || (hs.m_iType != m_iSockType) || (-1 == s_UDTUnited.newConnection(m_SocketID, addr, hs)))
      {
         // couldn't create a new connection, reject the request
         hs.m_iReqType = 1002;
      }

      packet.m_iID = id;

      m_pSndQueue.sendto(addr, packet);
   }

   return hs.m_iReqType;
}
Пример #21
0
        public UdtSocket locate(UDTSOCKET u, IPEndPoint peer, UDTSOCKET id, Int32 isn)
        {
            CGuard cg = new CGuard(m_ControlLock);

            UdtSocket i = null;

            m_Sockets.TryGetValue(u, out i);

            CGuard ag = new CGuard(i.m_AcceptLock);

            // look up the "peer" address in queued sockets set
            foreach (UDTSOCKET j1 in i.m_pQueuedSockets)
            {
                UdtSocket k1 = null;
                m_Sockets.TryGetValue(j1, out k1);
                // this socket might have been closed and moved m_ClosedSockets
                if (k1 == null)
                    continue;

                if (CIPAddress.ipcmp(peer, k1.m_pPeerAddr, i.m_iIPversion))
                {
                    if ((id == k1.m_PeerID) && (isn == k1.m_iISN))
                        return k1;
                }
            }

            // look up the "peer" address in accept sockets set
            foreach (UDTSOCKET j1 in i.m_pAcceptSockets)
            {
                UdtSocket k2 = null;
                m_Sockets.TryGetValue(j2, out k2);
                // this socket might have been closed and moved m_ClosedSockets
                if (k2 == null)
                    continue;

                if (CIPAddress.ipcmp(peer, k2.m_pPeerAddr, i.m_iIPversion))
                {
                    if ((id == k2.m_PeerID) && (isn == k2.m_iISN))
                        return k2;
                }
            }

            return null;
        }
Пример #22
0
      // Functionality:
      //    initialize a UDT entity and bind to a local address.
      // Parameters:
      //    None.
      // Returned value:
      //    None.

public void open()
{
   CGuard cg = new CGuard(m_ConnectionLock);

   // Initial sequence number, loss, acknowledgement, etc.
   m_iPktSize = m_iMSS - 28;
   m_iPayloadSize = m_iPktSize - CPacket.m_iPktHdrSize;

   m_iEXPCount = 1;
   m_iBandwidth = 1;
   m_iDeliveryRate = 16;
   m_iAckSeqNo = 0;
   m_ullLastAckTime = 0;

   // trace information
   m_StartTime = CClock.getTime();
   m_llSentTotal = m_llRecvTotal = m_iSndLossTotal = m_iRcvLossTotal = m_iRetransTotal = m_iSentACKTotal = m_iRecvACKTotal = m_iSentNAKTotal = m_iRecvNAKTotal = 0;
   m_LastSampleTime = CClock.getTime();
   m_llTraceSent = m_llTraceRecv = m_iTraceSndLoss = m_iTraceRcvLoss = m_iTraceRetrans = m_iSentACK = m_iRecvACK = m_iSentNAK = m_iRecvNAK = 0;
   m_llSndDuration = m_llSndDurationTotal = 0;

   // structures for queue
   if (null == m_pSNode)
      m_pSNode = new CSNode();
   m_pSNode.m_pUDT = this;
   m_pSNode.m_llTimeStamp = 1;
   m_pSNode.m_iHeapLoc = -1;

   if (null == m_pRNode)
      m_pRNode = new CRNode();
   m_pRNode.m_pUDT = this;
   m_pRNode.m_llTimeStamp = 1;
   m_pRNode.m_pPrev = m_pRNode.m_pNext = null;
   m_pRNode.m_bOnList = false;

   m_iRTT = 10 * m_iSYNInterval;
   m_iRTTVar = m_iRTT >> 1;
   m_ullCPUFrequency = CClock.getCPUFrequency();

   // set up the timers
   m_ullSYNInt = m_iSYNInterval * m_ullCPUFrequency;
   
   m_ullACKInt = m_ullSYNInt;
   m_ullNAKInt = (m_iRTT + 4 * m_iRTTVar) * m_ullCPUFrequency;
   m_ullEXPInt = (m_iRTT + 4 * m_iRTTVar) * m_ullCPUFrequency + m_ullSYNInt;
   m_ullMinEXPInt = 100000 * m_ullCPUFrequency;

   CClock.rdtsc(m_ullNextACKTime);
   m_ullNextACKTime += m_ullSYNInt;
   CClock.rdtsc(m_ullNextNAKTime);
   m_ullNextNAKTime += m_ullNAKInt;
   CClock.rdtsc(m_ullNextEXPTime);
   m_ullNextEXPTime += m_ullEXPInt;

   m_iPktCount = 0;
   m_iLightACKCount = 1;

   m_ullTargetTime = 0;
   m_ullTimeDiff = 0;

   // Now UDT is opened.
   m_bOpened = true;
}
Пример #23
0
        public void updateMux(CUDT u, UdtSocket ls)
        {
            CGuard cg = new CGuard(m_ControlLock);

            //int port = (AF_INET == ls.m_iIPversion) ? ntohs(((sockaddr_in*)ls.m_pSelfAddr).sin_port) : ntohs(((sockaddr_in6*)ls.m_pSelfAddr).sin6_port);
            int port = ls.m_pSelfAddr.Port;

            // find the listener's address
            foreach (CMultiplexer i in m_vMultiplexer)
            {
                if (i.m_iPort == port)
                {
                    // reuse the existing multiplexer
                    ++i.m_iRefCount;
                    u.m_pSndQueue = i.m_pSndQueue;
                    u.m_pRcvQueue = i.m_pRcvQueue;
                    return;
                }
            }
        }
Пример #24
0
        // Functionality:
        //    Remove ALL the seq. no. that are not greater than the parameter.
        // Parameters:
        //    0) [in] seqno: sequence number.
        // Returned value:
        //    None.

        public override bool remove(int seqno)
        {
            CGuard listguard = new CGuard(m_ListLock);

            if (0 == m_iLength)
                return false;

            // Remove all from the head pointer to a node with a larger seq. no. or the list is empty
            int offset = CSeqNo.seqoff(m_piData1[m_iHead], seqno);
            int loc = (m_iHead + offset + m_iSize) % m_iSize;

            if (0 == offset)
            {
                // It is the head. Remove the head and point to the next node
                loc = (loc + 1) % m_iSize;

                if (-1 == m_piData2[m_iHead])
                    loc = m_piNext[m_iHead];
                else
                {
                    m_piData1[loc] = CSeqNo.incseq(seqno);
                    if (CSeqNo.seqcmp(m_piData2[m_iHead], CSeqNo.incseq(seqno)) > 0)
                        m_piData2[loc] = m_piData2[m_iHead];

                    m_piData2[m_iHead] = -1;

                    m_piNext[loc] = m_piNext[m_iHead];
                }

                m_piData1[m_iHead] = -1;

                if (m_iLastInsertPos == m_iHead)
                    m_iLastInsertPos = -1;

                m_iHead = loc;

                m_iLength--;
            }
            else if (offset > 0)
            {
                int h = m_iHead;

                if (seqno == m_piData1[loc])
                {
                    // target node is not empty, remove part/all of the seqno in the node.
                    int temp = loc;
                    loc = (loc + 1) % m_iSize;

                    if (-1 == m_piData2[temp])
                        m_iHead = m_piNext[temp];
                    else
                    {
                        // remove part, e.g., [3, 7] becomes [], [4, 7] after remove(3)
                        m_piData1[loc] = CSeqNo.incseq(seqno);
                        if (CSeqNo.seqcmp(m_piData2[temp], m_piData1[loc]) > 0)
                            m_piData2[loc] = m_piData2[temp];
                        m_iHead = loc;
                        m_piNext[loc] = m_piNext[temp];
                        m_piNext[temp] = loc;
                        m_piData2[temp] = -1;
                    }
                }
                else
                {
                    // target node is empty, check prior node
                    int i = m_iHead;
                    while ((-1 != m_piNext[i]) && (CSeqNo.seqcmp(m_piData1[m_piNext[i]], seqno) < 0))
                        i = m_piNext[i];

                    loc = (loc + 1) % m_iSize;

                    if (-1 == m_piData2[i])
                        m_iHead = m_piNext[i];
                    else if (CSeqNo.seqcmp(m_piData2[i], seqno) > 0)
                    {
                        // remove part/all seqno in the prior node
                        m_piData1[loc] = CSeqNo.incseq(seqno);
                        if (CSeqNo.seqcmp(m_piData2[i], m_piData1[loc]) > 0)
                            m_piData2[loc] = m_piData2[i];

                        m_piData2[i] = seqno;

                        m_piNext[loc] = m_piNext[i];
                        m_piNext[i] = loc;

                        m_iHead = loc;
                    }
                    else
                        m_iHead = m_piNext[i];
                }

                // Remove all nodes prior to the new head
                while (h != m_iHead)
                {
                    if (m_piData2[h] != -1)
                    {
                        m_iLength -= CSeqNo.seqlen(m_piData1[h], m_piData2[h]);
                        m_piData2[h] = -1;
                    }
                    else
                        m_iLength--;

                    m_piData1[h] = -1;

                    if (m_iLastInsertPos == h)
                        m_iLastInsertPos = -1;

                    h = m_piNext[h];
                }
            }

            return true;
        }
Пример #25
0
        public void checkBrokenSockets()
        {
            CGuard cg = new CGuard(m_ControlLock);

            // set of sockets To Be Closed and To Be Removed
            HashSet<UDTSOCKET> tbc = new HashSet<int>();
            HashSet<UDTSOCKET> tbr = new HashSet<int>();

            //for (map<UDTSOCKET, UdtSocket*>::iterator i = m_Sockets.begin(); i != m_Sockets.end(); ++ i)
            foreach (KeyValuePair<UDTSOCKET, UdtSocket> i in m_Sockets)
            {
                // check broken connection
                if (i.Value.m_pUDT.m_bBroken)
                {
                    // if there is still data in the receiver buffer, wait longer
                    if ((i.Value.m_pUDT.m_pRcvBuffer.getRcvDataSize() > 0) && (i.Value.m_pUDT.m_iBrokenCounter-- > 0))
                        continue;

                    //close broken connections and start removal timer
                    i.Value.m_Status = UDTSTATUS.CLOSED;
                    i.Value.m_TimeStamp = CClock.getTime();
                    tbc.Add(i.Key);
                    m_ClosedSockets[i.Key] = i.Value;

                    // remove from listener's queue
                    //map<UDTSOCKET, UdtSocket*>::iterator ls = m_Sockets.find(i.second.m_ListenSocket);
                    UdtSocket ls = null;
                    bool foundIt = m_Sockets.TryGetValue(i.Value.m_ListenSocket, out ls);
                    if (ls != null)
                    {
                        lock (ls.Value.m_AcceptLock)
                        {
                            ls.Value.m_pQueuedSockets.erase(i.Value.m_SocketID);
                            ls.Value.m_pAcceptSockets.erase(i.Value.m_SocketID);
                        }
                    }
                }
            }

            foreach (KeyValuePair<UDTSOCKET, UdtSocket> j in m_ClosedSockets)
            {
                // timeout 1 second to destroy a socket AND it has been removed from RcvUList
                if ((CClock.getTime() - j.Value.m_TimeStamp > 1000000) && ((null == j.Value.m_pUDT.m_pRNode) || !j.Value.m_pUDT.m_pRNode.m_bOnList))
                    tbr.Add(j.Key);

                // sockets cannot be removed here because it will invalidate the map iterator
            }

            // move closed sockets to the ClosedSockets structure
            foreach (UDTSOCKET sock in tbc)
            {
                m_Sockets.Remove(sock);
            }

            // remove those timeout sockets
            foreach (UDTSOCKET sock in tbr)
            {
                removeSocket(sock);
            }
        }
Пример #26
0
        // Functionality:
        //    Read the loss length.
        // Parameters:
        //    None.
        // Returned value:
        //    The length of the list.

        public override int getLossLength()
        {
            CGuard listguard = new CGuard(m_ListLock);

            return m_iLength;
        }
Пример #27
0
        // Functionality:
        //    release the UDT library.
        // Parameters:
        //    None.
        // Returned value:
        //    0 if success, otherwise -1 is returned.

        int cleanup()
        {
            CGuard gcinit = new CGuard(m_InitLock);

            //destroy CTimer.EventLock

            if (!m_bGCStatus)
                return 0;

            m_bClosing = true;
            m_GCStopCond.Set();
            m_GCThread.Join();

            m_GCThread.Join();
            m_GCStopLock.Close();
            m_GCStopCond.Close();

            m_bGCStatus = false;

            return 0;
        }
Пример #28
0
      // Functionality:
      //    Start listening to any connection request.
      // Parameters:
      //    None.
      // Returned value:
      //    None.

public void listen()
{
   CGuard cg = new CGuard(m_ConnectionLock);

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

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

   // listen can be called more than once
   if (m_bListening)
      return;

   // if there is already another socket listening on the same port
   if (m_pRcvQueue.setListener(this) < 0)
      throw new CUDTException(5, 11, 0);

   m_bListening = true;
}