Document the functions and have both use a millisecond timeout and check for interrupt.
Unified · Split
| @@ -189,8 +189,29 @@ int ff_is_multicast_address(struct sockaddr *addr) · 188 unmodified lines | ||
| 189 | 189 | return 0; |
| 190 | 190 | } |
| 191 | 191 | |
| 192 | +static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout, | |
| 193 | + AVIOInterruptCB *cb) | |
| 194 | +{ | |
| 195 | + int runs = timeout / POLLING_TIME; | |
| 196 | + int ret = 0; | |
| 197 | + | |
| 198 | + do { | |
| 199 | + if (ff_check_interrupt(cb)) | |
| 200 | + return AVERROR_EXIT; | |
| 201 | + ret = poll(p, nfds, POLLING_TIME); | |
| 202 | + if (ret != 0) | |
| 203 | + break; | |
| 204 | + } while (timeout < 0 || runs-- > 0); | |
| 205 | + | |
| 206 | + if (!ret) | |
| 207 | + return AVERROR(ETIMEDOUT); | |
| 208 | + if (ret < 0) | |
| 209 | + return AVERROR(errno); | |
| 210 | + return ret; | |
| 211 | +} | |
| 212 | + | |
| 192 | 213 | int ff_listen_bind(int fd, const struct sockaddr *addr, |
| 193 | − socklen_t addrlen, int timeout) | |
| 214 | + socklen_t addrlen, int timeout, URLContext *h) | |
| 194 | 215 | { |
| 195 | 216 | int ret; |
| 196 | 217 | int reuse = 1; |
| @@ -204,9 +225,9 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, · 7 unmodified lines | ||
| 204 | 225 | if (ret) |
| 205 | 226 | return ff_neterrno(); |
| 206 | 227 | |
| 207 | − ret = poll(&lp, 1, timeout >= 0 ? timeout : -1); | |
| 208 | − if (ret <= 0) | |
| 209 | − return AVERROR(ETIMEDOUT); | |
| 228 | + ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback); | |
| 229 | + if (ret < 0) | |
| 230 | + return ret; | |
| 210 | 231 | |
| 211 | 232 | ret = accept(fd, NULL, NULL); |
| 212 | 233 | if (ret < 0) |
| @@ -236,15 +257,9 @@ int ff_listen_connect(int fd, const struct sockaddr *addr, · 23 unmodified lines | ||
| 236 | 257 | continue; |
| 237 | 258 | case AVERROR(EINPROGRESS): |
| 238 | 259 | case AVERROR(EAGAIN): |
| 239 | − while (timeout--) { | |
| 240 | − if (ff_check_interrupt(&h->interrupt_callback)) | |
| 241 | − return AVERROR_EXIT; | |
| 242 | − ret = poll(&p, 1, 100); | |
| 243 | − if (ret > 0) | |
| 244 | − break; | |
| 245 | − } | |
| 246 | − if (ret <= 0) | |
| 247 | − return AVERROR(ETIMEDOUT); | |
| 260 | + ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback); | |
| 261 | + if (ret < 0) | |
| 262 | + return ret; | |
| 248 | 263 | optlen = sizeof(ret); |
| 249 | 264 | if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) |
| 250 | 265 | ret = AVUNERROR(ff_neterrno()); |
| @@ -210,9 +210,38 @@ const char *ff_gai_strerror(int ecode); · 209 unmodified lines | ||
| 210 | 210 | |
| 211 | 211 | int ff_is_multicast_address(struct sockaddr *addr); |
| 212 | 212 | |
| 213 | +#define POLLING_TIME 100 /// Time in milliseconds between interrupt check | |
| 214 | + | |
| 215 | +/** | |
| 216 | + * Bind to a file descriptor and poll for a connection. | |
| 217 | + * | |
| 218 | + * @param fd First argument of bind(). | |
| 219 | + * @param addr Second argument of bind(). | |
| 220 | + * @param addrlen Third argument of bind(). | |
| 221 | + * @param timeout Polling timeout in milliseconds. | |
| 222 | + * @param h URLContext providing interrupt check | |
| 223 | + * callback and logging context. | |
| 224 | + * @return A non-blocking file descriptor on success | |
| 225 | + * or an AVERROR on failure. | |
| 226 | + */ | |
| 213 | 227 | int ff_listen_bind(int fd, const struct sockaddr *addr, |
| 214 | − socklen_t addrlen, int timeout); | |
| 228 | + socklen_t addrlen, int timeout, | |
| 229 | + URLContext *h); | |
| 230 | + | |
| 231 | +/** | |
| 232 | + * Connect to a file descriptor and poll for result. | |
| 233 | + * | |
| 234 | + * @param fd First argument of connect(), | |
| 235 | + * will be set as non-blocking. | |
| 236 | + * @param addr Second argument of connect(). | |
| 237 | + * @param addrlen Third argument of connect(). | |
| 238 | + * @param timeout Polling timeout in milliseconds. | |
| 239 | + * @param h URLContext providing interrupt check | |
| 240 | + * callback and logging context. | |
| 241 | + * @return 0 on success, AVERROR on failure. | |
| 242 | + */ | |
| 215 | 243 | int ff_listen_connect(int fd, const struct sockaddr *addr, |
| 216 | 244 | socklen_t addrlen, int timeout, |
| 217 | 245 | URLContext *h); |
| 246 | + | |
| 218 | 247 | #endif /* AVFORMAT_NETWORK_H */ |
| @@ -92,13 +92,13 @@ static int tcp_open(URLContext *h, const char *uri, int flags) · 91 unmodified lines | ||
| 92 | 92 | |
| 93 | 93 | if (listen_socket) { |
| 94 | 94 | if ((fd = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, |
| 95 | − listen_timeout)) < 0) { | |
| 95 | + listen_timeout, h)) < 0) { | |
| 96 | 96 | ret = fd; |
| 97 | 97 | goto fail1; |
| 98 | 98 | } |
| 99 | 99 | } else { |
| 100 | 100 | if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, |
| 101 | − timeout, h)) < 0) { | |
| 101 | + timeout * 100, h)) < 0) { | |
| 102 | 102 | |
| 103 | 103 | if (ret == AVERROR_EXIT) |
| 104 | 104 | goto fail1; |