Browse code

Merge commit '9835abb6d63fb07613994ae90e72fef758149408'

* 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>

Michael Niedermayer authored on 2013/06/05 18:56:56
Showing 3 changed files
... ...
@@ -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;