Select has limitations on the fd values it could accept and silently
breaks when it is reached.
(cherry picked from commit a8475bbdb64e638bd8161df9647876fd23f8a29a)
... | ... |
@@ -236,7 +236,6 @@ int ff_socket_nonblock(int socket, int enable) |
236 | 236 |
} |
237 | 237 |
#endif /* CONFIG_NETWORK */ |
238 | 238 |
|
239 |
-#if CONFIG_FFSERVER |
|
240 | 239 |
#if !HAVE_POLL_H |
241 | 240 |
int poll(struct pollfd *fds, nfds_t numfds, int timeout) |
242 | 241 |
{ |
... | ... |
@@ -305,5 +304,3 @@ int poll(struct pollfd *fds, nfds_t numfds, int timeout) |
305 | 305 |
return rc; |
306 | 306 |
} |
307 | 307 |
#endif /* HAVE_POLL_H */ |
308 |
-#endif /* CONFIG_FFSERVER */ |
|
309 |
- |
... | ... |
@@ -34,8 +34,8 @@ |
34 | 34 |
#include "network.h" |
35 | 35 |
#include "os_support.h" |
36 | 36 |
#include <fcntl.h> |
37 |
-#if HAVE_SYS_SELECT_H |
|
38 |
-#include <sys/select.h> |
|
37 |
+#if HAVE_POLL_H |
|
38 |
+#include <sys/poll.h> |
|
39 | 39 |
#endif |
40 | 40 |
#include <sys/time.h> |
41 | 41 |
|
... | ... |
@@ -221,9 +221,9 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) |
221 | 221 |
RTPContext *s = h->priv_data; |
222 | 222 |
struct sockaddr_storage from; |
223 | 223 |
socklen_t from_len; |
224 |
- int len, fd_max, n; |
|
225 |
- fd_set rfds; |
|
226 |
- struct timeval tv; |
|
224 |
+ int len, n; |
|
225 |
+ struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}}; |
|
226 |
+ |
|
227 | 227 |
#if 0 |
228 | 228 |
for(;;) { |
229 | 229 |
from_len = sizeof(from); |
... | ... |
@@ -242,18 +242,10 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) |
242 | 242 |
if (url_interrupt_cb()) |
243 | 243 |
return AVERROR(EINTR); |
244 | 244 |
/* build fdset to listen to RTP and RTCP packets */ |
245 |
- FD_ZERO(&rfds); |
|
246 |
- fd_max = s->rtp_fd; |
|
247 |
- FD_SET(s->rtp_fd, &rfds); |
|
248 |
- if (s->rtcp_fd > fd_max) |
|
249 |
- fd_max = s->rtcp_fd; |
|
250 |
- FD_SET(s->rtcp_fd, &rfds); |
|
251 |
- tv.tv_sec = 0; |
|
252 |
- tv.tv_usec = 100 * 1000; |
|
253 |
- n = select(fd_max + 1, &rfds, NULL, NULL, &tv); |
|
245 |
+ n = poll(p, 2, 100); |
|
254 | 246 |
if (n > 0) { |
255 | 247 |
/* first try RTCP */ |
256 |
- if (FD_ISSET(s->rtcp_fd, &rfds)) { |
|
248 |
+ if (p[1].revents & POLLIN) { |
|
257 | 249 |
from_len = sizeof(from); |
258 | 250 |
len = recvfrom (s->rtcp_fd, buf, size, 0, |
259 | 251 |
(struct sockaddr *)&from, &from_len); |
... | ... |
@@ -266,7 +258,7 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size) |
266 | 266 |
break; |
267 | 267 |
} |
268 | 268 |
/* then RTP */ |
269 |
- if (FD_ISSET(s->rtp_fd, &rfds)) { |
|
269 |
+ if (p[0].revents & POLLIN) { |
|
270 | 270 |
from_len = sizeof(from); |
271 | 271 |
len = recvfrom (s->rtp_fd, buf, size, 0, |
272 | 272 |
(struct sockaddr *)&from, &from_len); |
... | ... |
@@ -26,8 +26,8 @@ |
26 | 26 |
#include "avformat.h" |
27 | 27 |
|
28 | 28 |
#include <sys/time.h> |
29 |
-#if HAVE_SYS_SELECT_H |
|
30 |
-#include <sys/select.h> |
|
29 |
+#if HAVE_POLL_H |
|
30 |
+#include <poll.h> |
|
31 | 31 |
#endif |
32 | 32 |
#include <strings.h> |
33 | 33 |
#include "internal.h" |
... | ... |
@@ -44,11 +44,11 @@ |
44 | 44 |
//#define DEBUG |
45 | 45 |
//#define DEBUG_RTP_TCP |
46 | 46 |
|
47 |
-/* Timeout values for socket select, in ms, |
|
47 |
+/* Timeout values for socket poll, in ms, |
|
48 | 48 |
* and read_packet(), in seconds */ |
49 |
-#define SELECT_TIMEOUT_MS 100 |
|
49 |
+#define POLL_TIMEOUT_MS 100 |
|
50 | 50 |
#define READ_PACKET_TIMEOUT_S 10 |
51 |
-#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / SELECT_TIMEOUT_MS |
|
51 |
+#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_TIMEOUT_MS |
|
52 | 52 |
#define SDP_MAX_SIZE 16384 |
53 | 53 |
#define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH |
54 | 54 |
|
... | ... |
@@ -429,8 +429,14 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1, |
429 | 429 |
} |
430 | 430 |
} |
431 | 431 |
|
432 |
+/** |
|
433 |
+ * Parse the sdp description and allocate the rtp streams and the |
|
434 |
+ * pollfd array used for udp ones. |
|
435 |
+ */ |
|
436 |
+ |
|
432 | 437 |
int ff_sdp_parse(AVFormatContext *s, const char *content) |
433 | 438 |
{ |
439 |
+ RTSPState *rt = s->priv_data; |
|
434 | 440 |
const char *p; |
435 | 441 |
int letter; |
436 | 442 |
/* Some SDP lines, particularly for Realmedia or ASF RTSP streams, |
... | ... |
@@ -470,6 +476,8 @@ int ff_sdp_parse(AVFormatContext *s, const char *content) |
470 | 470 |
if (*p == '\n') |
471 | 471 |
p++; |
472 | 472 |
} |
473 |
+ rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1)); |
|
474 |
+ if (!rt->p) return AVERROR(ENOMEM); |
|
473 | 475 |
return 0; |
474 | 476 |
} |
475 | 477 |
#endif /* CONFIG_RTPDEC */ |
... | ... |
@@ -531,6 +539,7 @@ void ff_rtsp_close_streams(AVFormatContext *s) |
531 | 531 |
av_close_input_stream (rt->asf_ctx); |
532 | 532 |
rt->asf_ctx = NULL; |
533 | 533 |
} |
534 |
+ av_free(rt->p); |
|
534 | 535 |
av_free(rt->recvbuf); |
535 | 536 |
} |
536 | 537 |
|
... | ... |
@@ -1554,55 +1563,51 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st, |
1554 | 1554 |
{ |
1555 | 1555 |
RTSPState *rt = s->priv_data; |
1556 | 1556 |
RTSPStream *rtsp_st; |
1557 |
- fd_set rfds; |
|
1558 |
- int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0; |
|
1559 |
- struct timeval tv; |
|
1557 |
+ int n, i, ret, tcp_fd, timeout_cnt = 0; |
|
1558 |
+ int max_p = 0; |
|
1559 |
+ struct pollfd *p = rt->p; |
|
1560 | 1560 |
|
1561 | 1561 |
for (;;) { |
1562 | 1562 |
if (url_interrupt_cb()) |
1563 | 1563 |
return AVERROR(EINTR); |
1564 | 1564 |
if (wait_end && wait_end - av_gettime() < 0) |
1565 | 1565 |
return AVERROR(EAGAIN); |
1566 |
- FD_ZERO(&rfds); |
|
1566 |
+ max_p = 0; |
|
1567 | 1567 |
if (rt->rtsp_hd) { |
1568 |
- tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd); |
|
1569 |
- FD_SET(tcp_fd, &rfds); |
|
1568 |
+ tcp_fd = url_get_file_handle(rt->rtsp_hd); |
|
1569 |
+ p[max_p].fd = tcp_fd; |
|
1570 |
+ p[max_p++].events = POLLIN; |
|
1570 | 1571 |
} else { |
1571 |
- fd_max = 0; |
|
1572 | 1572 |
tcp_fd = -1; |
1573 | 1573 |
} |
1574 | 1574 |
for (i = 0; i < rt->nb_rtsp_streams; i++) { |
1575 | 1575 |
rtsp_st = rt->rtsp_streams[i]; |
1576 | 1576 |
if (rtsp_st->rtp_handle) { |
1577 |
- fd = url_get_file_handle(rtsp_st->rtp_handle); |
|
1578 |
- fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); |
|
1579 |
- if (FFMAX(fd, fd_rtcp) > fd_max) |
|
1580 |
- fd_max = FFMAX(fd, fd_rtcp); |
|
1581 |
- FD_SET(fd, &rfds); |
|
1582 |
- FD_SET(fd_rtcp, &rfds); |
|
1577 |
+ p[max_p].fd = url_get_file_handle(rtsp_st->rtp_handle); |
|
1578 |
+ p[max_p++].events = POLLIN; |
|
1579 |
+ p[max_p].fd = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); |
|
1580 |
+ p[max_p++].events = POLLIN; |
|
1583 | 1581 |
} |
1584 | 1582 |
} |
1585 |
- tv.tv_sec = 0; |
|
1586 |
- tv.tv_usec = SELECT_TIMEOUT_MS * 1000; |
|
1587 |
- n = select(fd_max + 1, &rfds, NULL, NULL, &tv); |
|
1583 |
+ n = poll(p, max_p, POLL_TIMEOUT_MS); |
|
1588 | 1584 |
if (n > 0) { |
1585 |
+ int j = 1 - (tcp_fd == -1); |
|
1589 | 1586 |
timeout_cnt = 0; |
1590 | 1587 |
for (i = 0; i < rt->nb_rtsp_streams; i++) { |
1591 | 1588 |
rtsp_st = rt->rtsp_streams[i]; |
1592 | 1589 |
if (rtsp_st->rtp_handle) { |
1593 |
- fd = url_get_file_handle(rtsp_st->rtp_handle); |
|
1594 |
- fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); |
|
1595 |
- if (FD_ISSET(fd_rtcp, &rfds) || FD_ISSET(fd, &rfds)) { |
|
1590 |
+ if (p[j].revents & POLLIN || p[j+1].revents & POLLIN) { |
|
1596 | 1591 |
ret = url_read(rtsp_st->rtp_handle, buf, buf_size); |
1597 | 1592 |
if (ret > 0) { |
1598 | 1593 |
*prtsp_st = rtsp_st; |
1599 | 1594 |
return ret; |
1600 | 1595 |
} |
1601 | 1596 |
} |
1597 |
+ j+=2; |
|
1602 | 1598 |
} |
1603 | 1599 |
} |
1604 | 1600 |
#if CONFIG_RTSP_DEMUXER |
1605 |
- if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) { |
|
1601 |
+ if (tcp_fd != -1 && p[0].revents & POLLIN) { |
|
1606 | 1602 |
RTSPMessageHeader reply; |
1607 | 1603 |
|
1608 | 1604 |
ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL); |
... | ... |
@@ -22,8 +22,8 @@ |
22 | 22 |
#include "avformat.h" |
23 | 23 |
|
24 | 24 |
#include <sys/time.h> |
25 |
-#if HAVE_SYS_SELECT_H |
|
26 |
-#include <sys/select.h> |
|
25 |
+#if HAVE_POLL_H |
|
26 |
+#include <poll.h> |
|
27 | 27 |
#endif |
28 | 28 |
#include "network.h" |
29 | 29 |
#include "rtsp.h" |
... | ... |
@@ -172,23 +172,16 @@ static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt) |
172 | 172 |
{ |
173 | 173 |
RTSPState *rt = s->priv_data; |
174 | 174 |
RTSPStream *rtsp_st; |
175 |
- fd_set rfds; |
|
176 |
- int n, tcp_fd; |
|
177 |
- struct timeval tv; |
|
175 |
+ int n; |
|
176 |
+ struct pollfd p = {url_get_file_handle(rt->rtsp_hd), POLLIN, 0}; |
|
178 | 177 |
AVFormatContext *rtpctx; |
179 | 178 |
int ret; |
180 | 179 |
|
181 |
- tcp_fd = url_get_file_handle(rt->rtsp_hd); |
|
182 |
- |
|
183 | 180 |
while (1) { |
184 |
- FD_ZERO(&rfds); |
|
185 |
- FD_SET(tcp_fd, &rfds); |
|
186 |
- tv.tv_sec = 0; |
|
187 |
- tv.tv_usec = 0; |
|
188 |
- n = select(tcp_fd + 1, &rfds, NULL, NULL, &tv); |
|
181 |
+ n = poll(&p, 1, 0); |
|
189 | 182 |
if (n <= 0) |
190 | 183 |
break; |
191 |
- if (FD_ISSET(tcp_fd, &rfds)) { |
|
184 |
+ if (p.revents & POLLIN) { |
|
192 | 185 |
RTSPMessageHeader reply; |
193 | 186 |
|
194 | 187 |
/* Don't let ff_rtsp_read_reply handle interleaved packets, |
... | ... |
@@ -25,8 +25,8 @@ |
25 | 25 |
#include "network.h" |
26 | 26 |
#include "os_support.h" |
27 | 27 |
#include "internal.h" |
28 |
-#if HAVE_SYS_SELECT_H |
|
29 |
-#include <sys/select.h> |
|
28 |
+#if HAVE_POLL_H |
|
29 |
+#include <poll.h> |
|
30 | 30 |
#endif |
31 | 31 |
#include <sys/time.h> |
32 | 32 |
|
... | ... |
@@ -183,19 +183,15 @@ static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt) |
183 | 183 |
struct SAPState *sap = s->priv_data; |
184 | 184 |
int fd = url_get_file_handle(sap->ann_fd); |
185 | 185 |
int n, ret; |
186 |
- fd_set rfds; |
|
187 |
- struct timeval tv; |
|
186 |
+ struct pollfd p = {fd, POLLIN, 0}; |
|
188 | 187 |
uint8_t recvbuf[1500]; |
189 | 188 |
|
190 | 189 |
if (sap->eof) |
191 | 190 |
return AVERROR_EOF; |
192 | 191 |
|
193 | 192 |
while (1) { |
194 |
- FD_ZERO(&rfds); |
|
195 |
- FD_SET(fd, &rfds); |
|
196 |
- tv.tv_sec = tv.tv_usec = 0; |
|
197 |
- n = select(fd + 1, &rfds, NULL, NULL, &tv); |
|
198 |
- if (n <= 0 || !FD_ISSET(fd, &rfds)) |
|
193 |
+ n = poll(&p, 1, 0); |
|
194 |
+ if (n <= 0 || !(p.revents & POLLIN)) |
|
199 | 195 |
break; |
200 | 196 |
ret = url_read(sap->ann_fd, recvbuf, sizeof(recvbuf)); |
201 | 197 |
if (ret >= 8) { |
... | ... |
@@ -23,8 +23,8 @@ |
23 | 23 |
#include "internal.h" |
24 | 24 |
#include "network.h" |
25 | 25 |
#include "os_support.h" |
26 |
-#if HAVE_SYS_SELECT_H |
|
27 |
-#include <sys/select.h> |
|
26 |
+#if HAVE_POLL_H |
|
27 |
+#include <poll.h> |
|
28 | 28 |
#endif |
29 | 29 |
#include <sys/time.h> |
30 | 30 |
|
... | ... |
@@ -38,9 +38,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
38 | 38 |
struct addrinfo hints, *ai, *cur_ai; |
39 | 39 |
int port, fd = -1; |
40 | 40 |
TCPContext *s = NULL; |
41 |
- fd_set wfds, efds; |
|
42 |
- int fd_max, ret; |
|
43 |
- struct timeval tv; |
|
41 |
+ int ret; |
|
44 | 42 |
socklen_t optlen; |
45 | 43 |
char hostname[1024],proto[1024],path[1024]; |
46 | 44 |
char portstr[10]; |
... | ... |
@@ -73,6 +71,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
73 | 73 |
redo: |
74 | 74 |
ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); |
75 | 75 |
if (ret < 0) { |
76 |
+ struct pollfd p = {fd, POLLOUT, 0}; |
|
76 | 77 |
if (ff_neterrno() == FF_NETERROR(EINTR)) { |
77 | 78 |
if (url_interrupt_cb()) |
78 | 79 |
goto fail1; |
... | ... |
@@ -88,15 +87,8 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
88 | 88 |
ret = AVERROR(EINTR); |
89 | 89 |
goto fail1; |
90 | 90 |
} |
91 |
- fd_max = fd; |
|
92 |
- FD_ZERO(&wfds); |
|
93 |
- FD_ZERO(&efds); |
|
94 |
- FD_SET(fd, &wfds); |
|
95 |
- FD_SET(fd, &efds); |
|
96 |
- tv.tv_sec = 0; |
|
97 |
- tv.tv_usec = 100 * 1000; |
|
98 |
- ret = select(fd_max + 1, NULL, &wfds, &efds, &tv); |
|
99 |
- if (ret > 0 && (FD_ISSET(fd, &wfds) || FD_ISSET(fd, &efds))) |
|
91 |
+ ret = poll(&p, 1, 100); |
|
92 |
+ if (ret > 0) |
|
100 | 93 |
break; |
101 | 94 |
} |
102 | 95 |
|
... | ... |
@@ -140,20 +132,14 @@ static int tcp_open(URLContext *h, const char *uri, int flags) |
140 | 140 |
static int tcp_read(URLContext *h, uint8_t *buf, int size) |
141 | 141 |
{ |
142 | 142 |
TCPContext *s = h->priv_data; |
143 |
- int len, fd_max, ret; |
|
144 |
- fd_set rfds; |
|
145 |
- struct timeval tv; |
|
143 |
+ struct pollfd p = {s->fd, POLLIN, 0}; |
|
144 |
+ int len, ret; |
|
146 | 145 |
|
147 | 146 |
for (;;) { |
148 | 147 |
if (url_interrupt_cb()) |
149 | 148 |
return AVERROR(EINTR); |
150 |
- fd_max = s->fd; |
|
151 |
- FD_ZERO(&rfds); |
|
152 |
- FD_SET(s->fd, &rfds); |
|
153 |
- tv.tv_sec = 0; |
|
154 |
- tv.tv_usec = 100 * 1000; |
|
155 |
- ret = select(fd_max + 1, &rfds, NULL, NULL, &tv); |
|
156 |
- if (ret > 0 && FD_ISSET(s->fd, &rfds)) { |
|
149 |
+ ret = poll(&p, 1, 100); |
|
150 |
+ if (ret == 1 && p.revents & POLLIN) { |
|
157 | 151 |
len = recv(s->fd, buf, size, 0); |
158 | 152 |
if (len < 0) { |
159 | 153 |
if (ff_neterrno() != FF_NETERROR(EINTR) && |
... | ... |
@@ -171,21 +157,15 @@ static int tcp_read(URLContext *h, uint8_t *buf, int size) |
171 | 171 |
static int tcp_write(URLContext *h, const uint8_t *buf, int size) |
172 | 172 |
{ |
173 | 173 |
TCPContext *s = h->priv_data; |
174 |
- int ret, size1, fd_max, len; |
|
175 |
- fd_set wfds; |
|
176 |
- struct timeval tv; |
|
174 |
+ int ret, size1, len; |
|
175 |
+ struct pollfd p = {s->fd, POLLOUT, 0}; |
|
177 | 176 |
|
178 | 177 |
size1 = size; |
179 | 178 |
while (size > 0) { |
180 | 179 |
if (url_interrupt_cb()) |
181 | 180 |
return AVERROR(EINTR); |
182 |
- fd_max = s->fd; |
|
183 |
- FD_ZERO(&wfds); |
|
184 |
- FD_SET(s->fd, &wfds); |
|
185 |
- tv.tv_sec = 0; |
|
186 |
- tv.tv_usec = 100 * 1000; |
|
187 |
- ret = select(fd_max + 1, NULL, &wfds, NULL, &tv); |
|
188 |
- if (ret > 0 && FD_ISSET(s->fd, &wfds)) { |
|
181 |
+ ret = poll(&p, 1, 100); |
|
182 |
+ if (ret == 1 && p.revents & POLLOUT) { |
|
189 | 183 |
len = send(s->fd, buf, size, 0); |
190 | 184 |
if (len < 0) { |
191 | 185 |
if (ff_neterrno() != FF_NETERROR(EINTR) && |
... | ... |
@@ -31,8 +31,8 @@ |
31 | 31 |
#include "internal.h" |
32 | 32 |
#include "network.h" |
33 | 33 |
#include "os_support.h" |
34 |
-#if HAVE_SYS_SELECT_H |
|
35 |
-#include <sys/select.h> |
|
34 |
+#if HAVE_POLL_H |
|
35 |
+#include <poll.h> |
|
36 | 36 |
#endif |
37 | 37 |
#include <sys/time.h> |
38 | 38 |
|
... | ... |
@@ -432,25 +432,20 @@ static int udp_open(URLContext *h, const char *uri, int flags) |
432 | 432 |
static int udp_read(URLContext *h, uint8_t *buf, int size) |
433 | 433 |
{ |
434 | 434 |
UDPContext *s = h->priv_data; |
435 |
+ struct pollfd p = {s->udp_fd, POLLIN, 0}; |
|
435 | 436 |
int len; |
436 |
- fd_set rfds; |
|
437 | 437 |
int ret; |
438 |
- struct timeval tv; |
|
439 | 438 |
|
440 | 439 |
for(;;) { |
441 | 440 |
if (url_interrupt_cb()) |
442 | 441 |
return AVERROR(EINTR); |
443 |
- FD_ZERO(&rfds); |
|
444 |
- FD_SET(s->udp_fd, &rfds); |
|
445 |
- tv.tv_sec = 0; |
|
446 |
- tv.tv_usec = 100 * 1000; |
|
447 |
- ret = select(s->udp_fd + 1, &rfds, NULL, NULL, &tv); |
|
442 |
+ ret = poll(&p, 1, 100); |
|
448 | 443 |
if (ret < 0) { |
449 | 444 |
if (ff_neterrno() == FF_NETERROR(EINTR)) |
450 | 445 |
continue; |
451 | 446 |
return AVERROR(EIO); |
452 | 447 |
} |
453 |
- if (!(ret > 0 && FD_ISSET(s->udp_fd, &rfds))) |
|
448 |
+ if (!(ret == 1 && p.revents & POLLIN)) |
|
454 | 449 |
continue; |
455 | 450 |
len = recv(s->udp_fd, buf, size, 0); |
456 | 451 |
if (len < 0) { |