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