* commit '9835abb6d63fb07613994ae90e72fef758149408':
network: uniform ff_listen_bind and ff_listen_connect
Conflicts:
libavformat/network.c
libavformat/tcp.c
Merged-by: Michael Niedermayer <michaelni@gmx.at>
... | ... |
@@ -214,8 +214,29 @@ int ff_is_multicast_address(struct sockaddr *addr) |
214 | 214 |
return 0; |
215 | 215 |
} |
216 | 216 |
|
217 |
+static int ff_poll_interrupt(struct pollfd *p, nfds_t nfds, int timeout, |
|
218 |
+ AVIOInterruptCB *cb) |
|
219 |
+{ |
|
220 |
+ int runs = timeout / POLLING_TIME; |
|
221 |
+ int ret = 0; |
|
222 |
+ |
|
223 |
+ do { |
|
224 |
+ if (ff_check_interrupt(cb)) |
|
225 |
+ return AVERROR_EXIT; |
|
226 |
+ ret = poll(p, nfds, POLLING_TIME); |
|
227 |
+ if (ret != 0) |
|
228 |
+ break; |
|
229 |
+ } while (timeout <= 0 || runs-- > 0); |
|
230 |
+ |
|
231 |
+ if (!ret) |
|
232 |
+ return AVERROR(ETIMEDOUT); |
|
233 |
+ if (ret < 0) |
|
234 |
+ return AVERROR(errno); |
|
235 |
+ return ret; |
|
236 |
+} |
|
237 |
+ |
|
217 | 238 |
int ff_listen_bind(int fd, const struct sockaddr *addr, |
218 |
- socklen_t addrlen, int timeout) |
|
239 |
+ socklen_t addrlen, int timeout, URLContext *h) |
|
219 | 240 |
{ |
220 | 241 |
int ret; |
221 | 242 |
int reuse = 1; |
... | ... |
@@ -231,9 +252,9 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, |
231 | 231 |
if (ret) |
232 | 232 |
return ff_neterrno(); |
233 | 233 |
|
234 |
- ret = poll(&lp, 1, timeout >= 0 ? timeout : -1); |
|
235 |
- if (ret <= 0) |
|
236 |
- return AVERROR(ETIMEDOUT); |
|
234 |
+ ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback); |
|
235 |
+ if (ret < 0) |
|
236 |
+ return ret; |
|
237 | 237 |
|
238 | 238 |
ret = accept(fd, NULL, NULL); |
239 | 239 |
if (ret < 0) |
... | ... |
@@ -246,7 +267,7 @@ int ff_listen_bind(int fd, const struct sockaddr *addr, |
246 | 246 |
} |
247 | 247 |
|
248 | 248 |
int ff_listen_connect(int fd, const struct sockaddr *addr, |
249 |
- socklen_t addrlen, int rw_timeout, URLContext *h) |
|
249 |
+ socklen_t addrlen, int timeout, URLContext *h) |
|
250 | 250 |
{ |
251 | 251 |
struct pollfd p = {fd, POLLOUT, 0}; |
252 | 252 |
int64_t wait_started; |
... | ... |
@@ -264,16 +285,9 @@ int ff_listen_connect(int fd, const struct sockaddr *addr, |
264 | 264 |
continue; |
265 | 265 |
case AVERROR(EINPROGRESS): |
266 | 266 |
case AVERROR(EAGAIN): |
267 |
- wait_started = av_gettime(); |
|
268 |
- do { |
|
269 |
- if (ff_check_interrupt(&h->interrupt_callback)) |
|
270 |
- return AVERROR_EXIT; |
|
271 |
- ret = poll(&p, 1, 100); |
|
272 |
- if (ret > 0) |
|
273 |
- break; |
|
274 |
- } while (!rw_timeout || (av_gettime() - wait_started < rw_timeout)); |
|
275 |
- if (ret <= 0) |
|
276 |
- return AVERROR(ETIMEDOUT); |
|
267 |
+ ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback); |
|
268 |
+ if (ret < 0) |
|
269 |
+ return ret; |
|
277 | 270 |
optlen = sizeof(ret); |
278 | 271 |
if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) |
279 | 272 |
ret = AVUNERROR(ff_neterrno()); |
... | ... |
@@ -223,9 +223,38 @@ const char *ff_gai_strerror(int ecode); |
223 | 223 |
|
224 | 224 |
int ff_is_multicast_address(struct sockaddr *addr); |
225 | 225 |
|
226 |
+#define POLLING_TIME 100 /// Time in milliseconds between interrupt check |
|
227 |
+ |
|
228 |
+/** |
|
229 |
+ * Bind to a file descriptor and poll for a connection. |
|
230 |
+ * |
|
231 |
+ * @param fd First argument of bind(). |
|
232 |
+ * @param addr Second argument of bind(). |
|
233 |
+ * @param addrlen Third argument of bind(). |
|
234 |
+ * @param timeout Polling timeout in milliseconds. |
|
235 |
+ * @param h URLContext providing interrupt check |
|
236 |
+ * callback and logging context. |
|
237 |
+ * @return A non-blocking file descriptor on success |
|
238 |
+ * or an AVERROR on failure. |
|
239 |
+ */ |
|
226 | 240 |
int ff_listen_bind(int fd, const struct sockaddr *addr, |
227 |
- socklen_t addrlen, int timeout); |
|
241 |
+ socklen_t addrlen, int timeout, |
|
242 |
+ URLContext *h); |
|
243 |
+ |
|
244 |
+/** |
|
245 |
+ * Connect to a file descriptor and poll for result. |
|
246 |
+ * |
|
247 |
+ * @param fd First argument of connect(), |
|
248 |
+ * will be set as non-blocking. |
|
249 |
+ * @param addr Second argument of connect(). |
|
250 |
+ * @param addrlen Third argument of connect(). |
|
251 |
+ * @param timeout Polling timeout in milliseconds. |
|
252 |
+ * @param h URLContext providing interrupt check |
|
253 |
+ * callback and logging context. |
|
254 |
+ * @return 0 on success, AVERROR on failure. |
|
255 |
+ */ |
|
228 | 256 |
int ff_listen_connect(int fd, const struct sockaddr *addr, |
229 | 257 |
socklen_t addrlen, int timeout, |
230 | 258 |
URLContext *h); |
259 |
+ |
|
231 | 260 |
#endif /* AVFORMAT_NETWORK_H */ |
... | ... |
@@ -115,13 +115,13 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
115 | 115 |
|
116 | 116 |
if (s->listen) { |
117 | 117 |
if ((fd = ff_listen_bind(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, |
118 |
- s->listen_timeout)) < 0) { |
|
118 |
+ s->listen_timeout, h)) < 0) { |
|
119 | 119 |
ret = fd; |
120 | 120 |
goto fail1; |
121 | 121 |
} |
122 | 122 |
} else { |
123 | 123 |
if ((ret = ff_listen_connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen, |
124 |
- h->rw_timeout, h)) < 0) { |
|
124 |
+ h->rw_timeout / 1000, h)) < 0) { |
|
125 | 125 |
|
126 | 126 |
if (ret == AVERROR_EXIT) |
127 | 127 |
goto fail1; |