| 270 | } |
| 271 | |
| 272 | bool TUdpSocket::RecvFrom(char* buf, size_t* size, TSockAddrPair* addr) { |
| 273 | Y_ASSERT(*size >= UDP_MAX_PACKET_SIZE); |
| 274 | for (;;) { |
| 275 | TAutoPtr<TUdpRecvPacket> result = RecvContinuationPacket(addr); |
| 276 | if (!!result) { |
| 277 | *size = result->DataSize; |
| 278 | memcpy(buf, result->Data.get() + result->DataStart, *size); |
| 279 | return true; |
| 280 | } |
| 281 | |
| 282 | const TIoVec v = CreateIoVec(buf, *size); |
| 283 | |
| 284 | char controllBuffer[CTRL_BUFFER_SIZE]; |
| 285 | TMsgHdr hdr = CreateRecvMsgHdr(&addr->RemoteAddr, v, controllBuffer); |
| 286 | |
| 287 | const int rv = S->RecvMsg(&hdr, 0); |
| 288 | if (rv < 0) |
| 289 | return false; |
| 290 | |
| 291 | NNetlibaSocket::ExtractDestinationAddress(hdr, &addr->MyAddr); |
| 292 | |
| 293 | if (CheckPacketIntegrity(buf, rv, *addr)) { |
| 294 | *size = ReadPacketDataSize(buf) + UDP_LOW_LEVEL_HEADER_SIZE; |
| 295 | |
| 296 | // it's packet with small packet optimization, we have to cache it for next calls. |
| 297 | if ((size_t)rv != *size) { |
| 298 | CacheContinuationUdpPacket(*ConvertToTUdpRecvPacket(buf, rv, *size), rv, *addr); |
| 299 | } |
| 300 | return true; |
| 301 | } |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | ////////////////////////////////////////////////////////////////////////////// |
| 306 | |