| 136 | } |
| 137 | |
| 138 | TNetSocket::ESendError TNetSocket::SendTo(const char* buf, int size, const sockaddr_in6& toAddress, const EFragFlag frag) const { |
| 139 | Y_ASSERT(size >= UDP_LOW_LEVEL_HEADER_SIZE); |
| 140 | ui32 crc = CalcChecksum(buf + UDP_LOW_LEVEL_HEADER_SIZE, size - UDP_LOW_LEVEL_HEADER_SIZE); |
| 141 | ui32 ipCrc = CalcAddressCrc(toAddress); |
| 142 | ui32 portCrc = toAddress.sin6_port; |
| 143 | *(ui32*)buf = crc + ipCrc + portCrc; |
| 144 | #ifdef SIMULATE_NETWORK_FAILURES |
| 145 | if ((RandomNumber<size_t>() % 3) == 0) |
| 146 | return true; // packet lost |
| 147 | if ((RandomNumber<size_t>() % 3) == 0) |
| 148 | (char&)(buf[RandomNumber<size_t>() % size]) += RandomNumber<size_t>(); // packet broken |
| 149 | #endif |
| 150 | |
| 151 | char tosBuffer[NNetlibaSocket::TOS_BUFFER_SIZE]; |
| 152 | void* t = NNetlibaSocket::CreateTos(Tos, tosBuffer); |
| 153 | const NNetlibaSocket::TIoVec iov = NNetlibaSocket::CreateIoVec((char*)buf, size); |
| 154 | NNetlibaSocket::TMsgHdr hdr = NNetlibaSocket::CreateSendMsgHdr(toAddress, iov, t); |
| 155 | |
| 156 | const int rv = s->SendMsg(&hdr, 0, frag); |
| 157 | if (rv < 0) { |
| 158 | if (errno == EHOSTUNREACH || errno == ENETUNREACH) { |
| 159 | return SEND_NO_ROUTE_TO_HOST; |
| 160 | } else { |
| 161 | return SEND_BUFFER_OVERFLOW; |
| 162 | } |
| 163 | } |
| 164 | Y_ASSERT(rv == size); |
| 165 | return SEND_OK; |
| 166 | } |
| 167 | |
| 168 | inline bool CrcMatches(ui32 pktCrc, ui32 crc, const sockaddr_in6& addr) { |
| 169 | Y_ASSERT(LocalHostFound); |