Esempio n. 1
0
        // Functionality:
        //    Receive a packet from the channel and record the source address.
        // Parameters:
        //    0) [in] addr: pointer to the source address.
        //    1) [in] packet: reference to a CPacket entity.
        // Returned value:
        //    Actual size of data received.

        public int recvfrom(IPAddress addr, CPacket packet)
{
      DWORD size = CPacket.m_iPktHdrSize + packet.getLength();
      DWORD flag = 0;
      int addrsize = (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);

      int res = WSARecvFrom(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, &flag, addr, &addrsize, null, null);
      res = (0 == res) ? size : -1;

   if (res <= 0)
   {
      packet.setLength(-1);
      return -1;
   }

   packet.setLength(res - CPacket.m_iPktHdrSize);

   // convert back into local host order
   //for (int i = 0; i < 4; ++ i)
   //   packet.m_nHeader[i] = ntohl(packet.m_nHeader[i]);
   uint* p = packet.m_nHeader;
   for (int i = 0; i < 4; ++ i)
   {
      *p = ntohl(*p);
      ++ p;
   }

   if (packet.getFlag())
      for (int j = 0, n = packet.getLength() / 4; j < n; ++ j)
         *((uint *)packet.m_pcData + j) = ntohl(*((uint *)packet.m_pcData + j));

   return packet.getLength();
        }
Esempio n. 2
0
        // Functionality:
        //    Send out a packet to a given address.
        // Parameters:
        //    1) [in] addr: destination address
        //    2) [in] packet: packet to be sent out
        // Returned value:
        //    Size of data sent out.

        public int sendto(IPEndPoint addr, CPacket packet)
        {
            // send out the packet immediately (high priority), this is a control packet
            m_pChannel.sendto(addr, packet);

            return packet.getLength();
        }
Esempio n. 3
0
        public void storePkt(Int32 id, CPacket pkt)
        {
            m_PassLock.WaitOne(-1);

            // if the packet already exists for the ID
            // then replace it, otherwise, add it
            if (m_mBuffer.ContainsKey(id))
            {
                m_mBuffer.Remove(id);
            }

            m_mBuffer.Add(id, pkt);

            m_PassLock.ReleaseMutex();
            m_PassCond.Set();
        }
Esempio n. 4
0
        // Functionality:
        //    Send a packet to the given address.
        // Parameters:
        //    0) [in] addr: pointer to the destination address.
        //    1) [in] packet: reference to a CPacket entity.
        // Returned value:
        //    Actual size of data sent.

        public int sendto(IPEndPoint addr, CPacket packet)
{
   // convert control information into network order
   if (packet.getFlag() > 0)
      for (int i = 0, n = packet.getLength() / 4; i < n; ++ i)
         *((uint *)packet.m_pcData + i) = htonl(*((uint *)packet.m_pcData + i));

   // convert packet header into network order
   //for (int j = 0; j < 4; ++ j)
   //   packet.m_nHeader[j] = htonl(packet.m_nHeader[j]);
   uint* p = packet.m_nHeader;
   for (int j = 0; j < 4; ++ j)
   {
      *p = htonl(*p);
      ++ p;
   }

      DWORD size = CPacket.m_iPktHdrSize + packet.getLength();
      //int addrsize = (AF_INET == m_iIPversion) ? sizeof(sockaddr_in) : sizeof(sockaddr_in6);
      //int res = WSASendTo(m_iSocket, (LPWSABUF)packet.m_PacketVector, 2, &size, 0, addr, addrsize, null, null);
      //int res = m_iSocket.SendTo(Buffer, addr);
      int res = m_iSocket.SendTo(Buffer, 0, size, SocketFlags.None, addr);

      res = (0 == res) ? size : -1;

   // convert back into local host order
   //for (int k = 0; k < 4; ++ k)
   //   packet.m_nHeader[k] = ntohl(packet.m_nHeader[k]);
   p = packet.m_nHeader;
   for (int k = 0; k < 4; ++ k)
   {
      *p = ntohl(*p);
       ++ p;
   }

   if (packet.getFlag() > 0)
      for (int l = 0, n = packet.getLength() / 4; l < n; ++ l)
         packet.m_pcData[l] = ntohl(packet.m_pcData[l]);

   return res;
}
Esempio n. 5
0
        // Functionality:
        //    Clone this packet.
        // Parameters:
        //    None.
        // Returned value:
        //    Pointer to the new packet.
        CPacket clone()
        {
            CPacket pkt = new CPacket();
            m_nHeader.CopyTo(pkt.m_nHeader, m_iPktHdrSize);
            //pkt.m_pcData = new byte[m_PacketVector[1].iov_len];
            //memcpy(pkt.m_pcData, m_pcData, m_PacketVector[1].iov_len);
            pkt.m_PacketVector[1].iov_len = m_PacketVector[1].iov_len;

            return pkt;
        }
Esempio n. 6
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();
        }
Esempio n. 7
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;
}
Esempio n. 8
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;
}
Esempio n. 9
0
void processCtrl(CPacket ctrlpkt)
{
   // Just heard from the peer, reset the expiration count.
   m_iEXPCount = 1;
   if ((CSeqNo.incseq(m_iSndCurrSeqNo) == m_iSndLastAck) || (2 == ctrlpkt.getType()) || (3 == ctrlpkt.getType()))
   {
      m_ullEXPInt = m_ullMinEXPInt;
      CClock.rdtsc(out m_ullNextEXPTime);
      m_ullNextEXPTime += m_ullEXPInt;
   }

   switch (ctrlpkt.getType())
   {
   case 2: //010 - Acknowledgement
      {
      Int32 ack;

      // process a lite ACK
      if (4 == ctrlpkt.getLength())
      {
         ack = *(Int32 *)ctrlpkt.m_pcData;
         if (CSeqNo.seqcmp(ack, (Int32)(m_iSndLastAck)) >= 0)
         {
            m_iFlowWindowSize -= CSeqNo.seqoff((Int32)(m_iSndLastAck), ack);
            m_iSndLastAck = ack;
         }

         break;
      }

       // read ACK seq. no.
      ack = ctrlpkt.getAckSeqNo();

      // send ACK acknowledgement
      // ACK2 can be much less than ACK
      Int64 currtime = CClock.getTime();
      if ((currtime - m_ullSndLastAck2Time > (Int64)m_iSYNInterval) || (ack == m_iSndLastAck2))
      {
         sendCtrl(6, &ack);
         m_iSndLastAck2 = ack;
         m_ullSndLastAck2Time = currtime;
      }

      // Got data ACK
      ack = *(Int32 *)ctrlpkt.m_pcData;

      // check the validation of the ack
      if (CSeqNo.seqcmp(ack, CSeqNo.incseq(m_iSndCurrSeqNo)) > 0)
      {
         //this should not happen: attack or bug
         m_bBroken = true;
         m_iBrokenCounter = 0;
         break;
      }

      if (CSeqNo.seqcmp(ack, (Int32)(m_iSndLastAck)) >= 0)
      {
         // Update Flow Window Size, must update before and together with m_iSndLastAck
         m_iFlowWindowSize = *((Int32 *)ctrlpkt.m_pcData + 3);
         m_iSndLastAck = ack;
      }

      // protect packet retransmission
      CGuard.enterCS(m_AckLock);

      int offset = CSeqNo.seqoff((Int32)m_iSndLastDataAck, ack);
      if (offset <= 0)
      {
         // discard it if it is a repeated ACK
         CGuard.leaveCS(m_AckLock);
         break;
      }

      // acknowledge the sending buffer
      m_pSndBuffer.ackData(offset);

      // record total time used for sending
      m_llSndDuration += currtime - m_llSndDurationCounter;
      m_llSndDurationTotal += currtime - m_llSndDurationCounter;
      m_llSndDurationCounter = currtime;

      // update sending variables
      m_iSndLastDataAck = ack;
      m_pSndLossList.remove(CSeqNo.decseq((Int32)m_iSndLastDataAck));

      CGuard.leaveCS(m_AckLock);

         if (m_bSynSending)
            SetEvent(m_SendBlockCond);

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

      // Update RTT
      //m_iRTT = *((Int32 *)ctrlpkt.m_pcData + 1);
      //m_iRTTVar = *((Int32 *)ctrlpkt.m_pcData + 2);
      int rtt = *((Int32 *)ctrlpkt.m_pcData + 1);
      m_iRTTVar = (m_iRTTVar * 3 + abs(rtt - m_iRTT)) >> 2;
      m_iRTT = (m_iRTT * 7 + rtt) >> 3;

      m_pCC.setRTT(m_iRTT);

      m_ullMinEXPInt = (m_iRTT + 4 * m_iRTTVar) * m_ullCPUFrequency + m_ullSYNInt;
      if (m_ullMinEXPInt < 100000 * m_ullCPUFrequency)
          m_ullMinEXPInt = 100000 * m_ullCPUFrequency;

      if (ctrlpkt.getLength() > 16)
      {
         // Update Estimated Bandwidth and packet delivery rate
         if (*((Int32 *)ctrlpkt.m_pcData + 4) > 0)
            m_iDeliveryRate = (m_iDeliveryRate * 7 + *((Int32 *)ctrlpkt.m_pcData + 4)) >> 3;

         if (*((Int32 *)ctrlpkt.m_pcData + 5) > 0)
            m_iBandwidth = (m_iBandwidth * 7 + *((Int32 *)ctrlpkt.m_pcData + 5)) >> 3;

         m_pCC.setRcvRate(m_iDeliveryRate);
         m_pCC.setBandwidth(m_iBandwidth);
      }

      m_pCC.onACK(ack);
      // update CC parameters
      m_ullInterval = (Int64)(m_pCC.m_dPktSndPeriod * m_ullCPUFrequency);
      m_dCongestionWindow = m_pCC.m_dCWndSize;

      ++ m_iRecvACK;
      ++ m_iRecvACKTotal;

      break;
      }

   case 6: //110 - Acknowledgement of Acknowledgement
      {
      Int32 ack;
      int rtt = -1;

      // update RTT
      rtt = m_pACKWindow.acknowledge(ctrlpkt.getAckSeqNo(), ack);

      if (rtt <= 0)
         break;

      //if increasing delay detected...
      //   sendCtrl(4);

      // RTT EWMA
      m_iRTTVar = (m_iRTTVar * 3 + abs(rtt - m_iRTT)) >> 2;
      m_iRTT = (m_iRTT * 7 + rtt) >> 3;

      m_pCC.setRTT(m_iRTT);

      m_ullMinEXPInt = (m_iRTT + 4 * m_iRTTVar) * m_ullCPUFrequency + m_ullSYNInt;
      if (m_ullMinEXPInt < 100000 * m_ullCPUFrequency)
          m_ullMinEXPInt = 100000 * m_ullCPUFrequency;

      // update last ACK that has been received by the sender
      if (CSeqNo.seqcmp(ack, m_iRcvLastAckAck) > 0)
         m_iRcvLastAckAck = ack;

      break;
      }

   case 3: //011 - Loss Report
      {
      Int32* losslist = (Int32 *)(ctrlpkt.m_pcData);

      m_pCC.onLoss(losslist, ctrlpkt.getLength() / 4);
      // update CC parameters
      m_ullInterval = (Int64)(m_pCC.m_dPktSndPeriod * m_ullCPUFrequency);
      m_dCongestionWindow = m_pCC.m_dCWndSize;

      bool secure = true;

      // decode loss list message and insert loss into the sender loss list
      for (int i = 0, n = (int)(ctrlpkt.getLength() / 4); i < n; ++ i)
      {
         if (0 != (losslist[i] & 0x80000000))
         {
            if ((CSeqNo.seqcmp(losslist[i] & 0x7FFFFFFF, losslist[i + 1]) > 0) || (CSeqNo.seqcmp(losslist[i + 1], (Int32)(m_iSndCurrSeqNo)) > 0))
            {
               // seq_a must not be greater than seq_b; seq_b must not be greater than the most recent sent seq
               secure = false;
               break;
            }

            int num = 0;
            if (CSeqNo.seqcmp(losslist[i] & 0x7FFFFFFF, (Int32)(m_iSndLastAck)) >= 0)
               num = m_pSndLossList.insert(losslist[i] & 0x7FFFFFFF, losslist[i + 1]);
            else if (CSeqNo.seqcmp(losslist[i + 1], (Int32)(m_iSndLastAck)) >= 0)
               num = m_pSndLossList.insert((Int32)(m_iSndLastAck), losslist[i + 1]);

            m_iTraceSndLoss += num;
            m_iSndLossTotal += num;

            ++ i;
         }
         else if (CSeqNo.seqcmp(losslist[i], (Int32)(m_iSndLastAck)) >= 0)
         {
            if (CSeqNo.seqcmp(losslist[i], (Int32)(m_iSndCurrSeqNo)) > 0)
            {
               //seq_a must not be greater than the most recent sent seq
               secure = false;
               break;
            }

            int num = m_pSndLossList.insert(losslist[i], losslist[i]);

            m_iTraceSndLoss += num;
            m_iSndLossTotal += num;
         }
      }

      if (!secure)
      {
         //this should not happen: attack or bug
         m_bBroken = true;
         m_iBrokenCounter = 0;
         break;
      }

      // the lost packet (retransmission) should be sent out immediately
      m_pSndQueue.m_pSndUList.update(this);

      ++ m_iRecvNAK;
      ++ m_iRecvNAKTotal;

      break;
      }

   case 4: //100 - Delay Warning
      // One way packet delay is increasing, so decrease the sending rate
      m_ullInterval = (Int64)ceil(m_ullInterval * 1.125);
      m_iLastDecSeq = m_iSndCurrSeqNo;

      break;

   case 1: //001 - Keep-alive
      // The only purpose of keep-alive packet is to tell that the peer is still alive
      // nothing needs to be done.

      break;

   case 0: //000 - Handshake
      if ((((CHandShake*)(ctrlpkt.m_pcData)).m_iReqType > 0) || (m_bRendezvous && (((CHandShake*)(ctrlpkt.m_pcData)).m_iReqType != -2)))
      {
         // The peer side has not received the handshake message, so it keeps querying
         // resend the handshake packet

         CHandShake initdata;
         initdata.m_iISN = m_iISN;
         initdata.m_iMSS = m_iMSS;
         initdata.m_iFlightFlagSize = m_iFlightFlagSize;
         initdata.m_iReqType = (!m_bRendezvous) ? -1 : -2;
         initdata.m_iID = m_SocketID;
         sendCtrl(0, null, (char *)&initdata, sizeof(CHandShake));
      }

      break;

   case 5: //101 - Shutdown
      m_bShutdown = true;
      m_bClosing = true;
      m_bBroken = true;
      m_iBrokenCounter = 60;

      // Signal the sender and recver if they are waiting for data.
      releaseSynch();

      CClock.triggerEvent();

      break;

   case 7: //111 - Msg drop request
      m_pRcvBuffer.dropMsg(ctrlpkt.getMsgSeq());
      m_pRcvLossList.remove(*(Int32*)ctrlpkt.m_pcData, *(Int32*)(ctrlpkt.m_pcData + 4));

      break;

   case 32767: //0x7FFF - reserved and user defined messages
      m_pCC.processCustomMsg(&ctrlpkt);
      // update CC parameters
      m_ullInterval = (Int64)(m_pCC.m_dPktSndPeriod * m_ullCPUFrequency);
      m_dCongestionWindow = m_pCC.m_dCWndSize;

      break;

   default:
      break;
   }
}
Esempio n. 10
0
        // Functionality:
        //    Send a user defined control packet.
        // Parameters:
        //    0) [in] pkt: user defined packet.
        // Returned value:
        //    None.

        protected void sendCustomMsg(CPacket pkt)
        {
            CUDT u = CUDT.getUDTHandle(m_UDT);

            if (null != u)
            {
                pkt.m_iID = u.m_PeerID;
                u.m_pSndQueue.sendto(u.m_pPeerAddr, pkt);
            }
        }
Esempio n. 11
0
        // Functionality:
        //    Callback function to Process a user defined packet.
        // Parameters:
        //    0) [in] pkt: the user defined packet.
        // Returned value:
        //    None.

        public virtual void processCustomMsg(CPacket packet)
        {
        }
Esempio n. 12
0
        // Functionality:
        //    Callback function to be called when a data is received.
        // Parameters:
        //    0) [in] packet: the packet, including sequence number, and payload size.
        // Returned value:
        //    None.

        public virtual void onPktReceived(CPacket packet)
        {
        }
Esempio n. 13
0
        // Functionality:
        //    Callback function to be called when a data is sent.
        // Parameters:
        //    0) [in] seqno: the data sequence number.
        //    1) [in] size: the payload size.
        // Returned value:
        //    None.

        public virtual void onPktSent(CPacket packet)
        {
        }