-------------------------------------------------------------------------*\ * Recvfrom with timeout \*-------------------------------------------------------------------------*/
| 277 | * Recvfrom with timeout |
| 278 | \*-------------------------------------------------------------------------*/ |
| 279 | int socket_recvfrom(p_socket ps, char *data, size_t count, size_t *got, |
| 280 | SA *addr, socklen_t *len, p_timeout tm) |
| 281 | { |
| 282 | int err, prev = IO_DONE; |
| 283 | *got = 0; |
| 284 | if (*ps == SOCKET_INVALID) return IO_CLOSED; |
| 285 | for ( ;; ) { |
| 286 | int taken = recvfrom(*ps, data, (int) count, 0, addr, len); |
| 287 | if (taken > 0) { |
| 288 | *got = taken; |
| 289 | return IO_DONE; |
| 290 | } |
| 291 | if (taken == 0) return IO_CLOSED; |
| 292 | err = WSAGetLastError(); |
| 293 | /* On UDP, a connreset simply means the previous send failed. |
| 294 | * So we try again. |
| 295 | * On TCP, it means our socket is now useless, so the error passes. |
| 296 | * (We will loop again, exiting because the same error will happen) */ |
| 297 | if (err != WSAEWOULDBLOCK) { |
| 298 | if (err != WSAECONNRESET || prev == WSAECONNRESET) return err; |
| 299 | prev = err; |
| 300 | } |
| 301 | if ((err = socket_waitfd(ps, WAITFD_R, tm)) != IO_DONE) return err; |
| 302 | } |
| 303 | } |
| 304 | |
| 305 | /*-------------------------------------------------------------------------*\ |
| 306 | * Put socket into blocking mode |
nothing calls this directly
no test coverage detected