os: replace select with poll

Select has limitations on the fd values it could accept and silently
breaks when it is reached.
oldabi
Luca Barbato 14 years ago
parent 5ce5dbc5f3
commit a8475bbdb6
  1. 3
      libavformat/os_support.c
  2. 24
      libavformat/rtpproto.c
  3. 55
      libavformat/rtsp.c
  4. 5
      libavformat/rtsp.h
  5. 19
      libavformat/rtspenc.c
  6. 14
      libavformat/sapdec.c
  7. 48
      libavformat/tcp.c
  8. 15
      libavformat/udp.c

@ -236,7 +236,6 @@ int ff_socket_nonblock(int socket, int enable)
} }
#endif /* CONFIG_NETWORK */ #endif /* CONFIG_NETWORK */
#if CONFIG_FFSERVER
#if !HAVE_POLL_H #if !HAVE_POLL_H
int poll(struct pollfd *fds, nfds_t numfds, int timeout) int poll(struct pollfd *fds, nfds_t numfds, int timeout)
{ {
@ -305,5 +304,3 @@ int poll(struct pollfd *fds, nfds_t numfds, int timeout)
return rc; return rc;
} }
#endif /* HAVE_POLL_H */ #endif /* HAVE_POLL_H */
#endif /* CONFIG_FFSERVER */

@ -34,8 +34,8 @@
#include "network.h" #include "network.h"
#include "os_support.h" #include "os_support.h"
#include <fcntl.h> #include <fcntl.h>
#if HAVE_SYS_SELECT_H #if HAVE_POLL_H
#include <sys/select.h> #include <sys/poll.h>
#endif #endif
#include <sys/time.h> #include <sys/time.h>
@ -221,9 +221,9 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
RTPContext *s = h->priv_data; RTPContext *s = h->priv_data;
struct sockaddr_storage from; struct sockaddr_storage from;
socklen_t from_len; socklen_t from_len;
int len, fd_max, n; int len, n;
fd_set rfds; struct pollfd p[2] = {{s->rtp_fd, POLLIN, 0}, {s->rtcp_fd, POLLIN, 0}};
struct timeval tv;
#if 0 #if 0
for(;;) { for(;;) {
from_len = sizeof(from); from_len = sizeof(from);
@ -242,18 +242,10 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
if (url_interrupt_cb()) if (url_interrupt_cb())
return AVERROR(EINTR); return AVERROR(EINTR);
/* build fdset to listen to RTP and RTCP packets */ /* build fdset to listen to RTP and RTCP packets */
FD_ZERO(&rfds); n = poll(p, 2, 100);
fd_max = s->rtp_fd;
FD_SET(s->rtp_fd, &rfds);
if (s->rtcp_fd > fd_max)
fd_max = s->rtcp_fd;
FD_SET(s->rtcp_fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
if (n > 0) { if (n > 0) {
/* first try RTCP */ /* first try RTCP */
if (FD_ISSET(s->rtcp_fd, &rfds)) { if (p[1].revents & POLLIN) {
from_len = sizeof(from); from_len = sizeof(from);
len = recvfrom (s->rtcp_fd, buf, size, 0, len = recvfrom (s->rtcp_fd, buf, size, 0,
(struct sockaddr *)&from, &from_len); (struct sockaddr *)&from, &from_len);
@ -266,7 +258,7 @@ static int rtp_read(URLContext *h, uint8_t *buf, int size)
break; break;
} }
/* then RTP */ /* then RTP */
if (FD_ISSET(s->rtp_fd, &rfds)) { if (p[0].revents & POLLIN) {
from_len = sizeof(from); from_len = sizeof(from);
len = recvfrom (s->rtp_fd, buf, size, 0, len = recvfrom (s->rtp_fd, buf, size, 0,
(struct sockaddr *)&from, &from_len); (struct sockaddr *)&from, &from_len);

@ -26,8 +26,8 @@
#include "avformat.h" #include "avformat.h"
#include <sys/time.h> #include <sys/time.h>
#if HAVE_SYS_SELECT_H #if HAVE_POLL_H
#include <sys/select.h> #include <poll.h>
#endif #endif
#include <strings.h> #include <strings.h>
#include "internal.h" #include "internal.h"
@ -44,11 +44,11 @@
//#define DEBUG //#define DEBUG
//#define DEBUG_RTP_TCP //#define DEBUG_RTP_TCP
/* Timeout values for socket select, in ms, /* Timeout values for socket poll, in ms,
* and read_packet(), in seconds */ * and read_packet(), in seconds */
#define SELECT_TIMEOUT_MS 100 #define POLL_TIMEOUT_MS 100
#define READ_PACKET_TIMEOUT_S 10 #define READ_PACKET_TIMEOUT_S 10
#define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / SELECT_TIMEOUT_MS #define MAX_TIMEOUTS READ_PACKET_TIMEOUT_S * 1000 / POLL_TIMEOUT_MS
#define SDP_MAX_SIZE 16384 #define SDP_MAX_SIZE 16384
#define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH #define RECVBUF_SIZE 10 * RTP_MAX_PACKET_LENGTH
@ -429,8 +429,14 @@ static void sdp_parse_line(AVFormatContext *s, SDPParseState *s1,
} }
} }
/**
* Parse the sdp description and allocate the rtp streams and the
* pollfd array used for udp ones.
*/
int ff_sdp_parse(AVFormatContext *s, const char *content) int ff_sdp_parse(AVFormatContext *s, const char *content)
{ {
RTSPState *rt = s->priv_data;
const char *p; const char *p;
int letter; int letter;
/* Some SDP lines, particularly for Realmedia or ASF RTSP streams, /* Some SDP lines, particularly for Realmedia or ASF RTSP streams,
@ -470,6 +476,8 @@ int ff_sdp_parse(AVFormatContext *s, const char *content)
if (*p == '\n') if (*p == '\n')
p++; p++;
} }
rt->p = av_malloc(sizeof(struct pollfd)*2*(rt->nb_rtsp_streams+1));
if (!rt->p) return AVERROR(ENOMEM);
return 0; return 0;
} }
#endif /* CONFIG_RTPDEC */ #endif /* CONFIG_RTPDEC */
@ -531,6 +539,7 @@ void ff_rtsp_close_streams(AVFormatContext *s)
av_close_input_stream (rt->asf_ctx); av_close_input_stream (rt->asf_ctx);
rt->asf_ctx = NULL; rt->asf_ctx = NULL;
} }
av_free(rt->p);
av_free(rt->recvbuf); av_free(rt->recvbuf);
} }
@ -1554,55 +1563,51 @@ static int udp_read_packet(AVFormatContext *s, RTSPStream **prtsp_st,
{ {
RTSPState *rt = s->priv_data; RTSPState *rt = s->priv_data;
RTSPStream *rtsp_st; RTSPStream *rtsp_st;
fd_set rfds; int n, i, ret, tcp_fd, timeout_cnt = 0;
int fd, fd_rtcp, fd_max, n, i, ret, tcp_fd, timeout_cnt = 0; int max_p = 0;
struct timeval tv; struct pollfd *p = rt->p;
for (;;) { for (;;) {
if (url_interrupt_cb()) if (url_interrupt_cb())
return AVERROR(EINTR); return AVERROR(EINTR);
if (wait_end && wait_end - av_gettime() < 0) if (wait_end && wait_end - av_gettime() < 0)
return AVERROR(EAGAIN); return AVERROR(EAGAIN);
FD_ZERO(&rfds); max_p = 0;
if (rt->rtsp_hd) { if (rt->rtsp_hd) {
tcp_fd = fd_max = url_get_file_handle(rt->rtsp_hd); tcp_fd = url_get_file_handle(rt->rtsp_hd);
FD_SET(tcp_fd, &rfds); p[max_p].fd = tcp_fd;
p[max_p++].events = POLLIN;
} else { } else {
fd_max = 0;
tcp_fd = -1; tcp_fd = -1;
} }
for (i = 0; i < rt->nb_rtsp_streams; i++) { for (i = 0; i < rt->nb_rtsp_streams; i++) {
rtsp_st = rt->rtsp_streams[i]; rtsp_st = rt->rtsp_streams[i];
if (rtsp_st->rtp_handle) { if (rtsp_st->rtp_handle) {
fd = url_get_file_handle(rtsp_st->rtp_handle); p[max_p].fd = url_get_file_handle(rtsp_st->rtp_handle);
fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle); p[max_p++].events = POLLIN;
if (FFMAX(fd, fd_rtcp) > fd_max) p[max_p].fd = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
fd_max = FFMAX(fd, fd_rtcp); p[max_p++].events = POLLIN;
FD_SET(fd, &rfds);
FD_SET(fd_rtcp, &rfds);
} }
} }
tv.tv_sec = 0; n = poll(p, max_p, POLL_TIMEOUT_MS);
tv.tv_usec = SELECT_TIMEOUT_MS * 1000;
n = select(fd_max + 1, &rfds, NULL, NULL, &tv);
if (n > 0) { if (n > 0) {
int j = 1 - (tcp_fd == -1);
timeout_cnt = 0; timeout_cnt = 0;
for (i = 0; i < rt->nb_rtsp_streams; i++) { for (i = 0; i < rt->nb_rtsp_streams; i++) {
rtsp_st = rt->rtsp_streams[i]; rtsp_st = rt->rtsp_streams[i];
if (rtsp_st->rtp_handle) { if (rtsp_st->rtp_handle) {
fd = url_get_file_handle(rtsp_st->rtp_handle); if (p[j].revents & POLLIN || p[j+1].revents & POLLIN) {
fd_rtcp = rtp_get_rtcp_file_handle(rtsp_st->rtp_handle);
if (FD_ISSET(fd_rtcp, &rfds) || FD_ISSET(fd, &rfds)) {
ret = url_read(rtsp_st->rtp_handle, buf, buf_size); ret = url_read(rtsp_st->rtp_handle, buf, buf_size);
if (ret > 0) { if (ret > 0) {
*prtsp_st = rtsp_st; *prtsp_st = rtsp_st;
return ret; return ret;
} }
} }
j+=2;
} }
} }
#if CONFIG_RTSP_DEMUXER #if CONFIG_RTSP_DEMUXER
if (tcp_fd != -1 && FD_ISSET(tcp_fd, &rfds)) { if (tcp_fd != -1 && p[0].revents & POLLIN) {
RTSPMessageHeader reply; RTSPMessageHeader reply;
ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL); ret = ff_rtsp_read_reply(s, &reply, NULL, 0, NULL);

@ -326,6 +326,11 @@ typedef struct RTSPState {
* The number of returned packets * The number of returned packets
*/ */
uint64_t packets; uint64_t packets;
/**
* Polling array for udp
*/
struct pollfd *p;
} RTSPState; } RTSPState;
/** /**

@ -22,8 +22,8 @@
#include "avformat.h" #include "avformat.h"
#include <sys/time.h> #include <sys/time.h>
#if HAVE_SYS_SELECT_H #if HAVE_POLL_H
#include <sys/select.h> #include <poll.h>
#endif #endif
#include "network.h" #include "network.h"
#include "rtsp.h" #include "rtsp.h"
@ -172,23 +172,16 @@ static int rtsp_write_packet(AVFormatContext *s, AVPacket *pkt)
{ {
RTSPState *rt = s->priv_data; RTSPState *rt = s->priv_data;
RTSPStream *rtsp_st; RTSPStream *rtsp_st;
fd_set rfds; int n;
int n, tcp_fd; struct pollfd p = {url_get_file_handle(rt->rtsp_hd), POLLIN, 0};
struct timeval tv;
AVFormatContext *rtpctx; AVFormatContext *rtpctx;
int ret; int ret;
tcp_fd = url_get_file_handle(rt->rtsp_hd);
while (1) { while (1) {
FD_ZERO(&rfds); n = poll(&p, 1, 0);
FD_SET(tcp_fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 0;
n = select(tcp_fd + 1, &rfds, NULL, NULL, &tv);
if (n <= 0) if (n <= 0)
break; break;
if (FD_ISSET(tcp_fd, &rfds)) { if (p.revents & POLLIN) {
RTSPMessageHeader reply; RTSPMessageHeader reply;
/* Don't let ff_rtsp_read_reply handle interleaved packets, /* Don't let ff_rtsp_read_reply handle interleaved packets,

@ -25,8 +25,8 @@
#include "network.h" #include "network.h"
#include "os_support.h" #include "os_support.h"
#include "internal.h" #include "internal.h"
#if HAVE_SYS_SELECT_H #if HAVE_POLL_H
#include <sys/select.h> #include <poll.h>
#endif #endif
#include <sys/time.h> #include <sys/time.h>
@ -183,19 +183,15 @@ static int sap_fetch_packet(AVFormatContext *s, AVPacket *pkt)
struct SAPState *sap = s->priv_data; struct SAPState *sap = s->priv_data;
int fd = url_get_file_handle(sap->ann_fd); int fd = url_get_file_handle(sap->ann_fd);
int n, ret; int n, ret;
fd_set rfds; struct pollfd p = {fd, POLLIN, 0};
struct timeval tv;
uint8_t recvbuf[1500]; uint8_t recvbuf[1500];
if (sap->eof) if (sap->eof)
return AVERROR_EOF; return AVERROR_EOF;
while (1) { while (1) {
FD_ZERO(&rfds); n = poll(&p, 1, 0);
FD_SET(fd, &rfds); if (n <= 0 || !(p.revents & POLLIN))
tv.tv_sec = tv.tv_usec = 0;
n = select(fd + 1, &rfds, NULL, NULL, &tv);
if (n <= 0 || !FD_ISSET(fd, &rfds))
break; break;
ret = url_read(sap->ann_fd, recvbuf, sizeof(recvbuf)); ret = url_read(sap->ann_fd, recvbuf, sizeof(recvbuf));
if (ret >= 8) { if (ret >= 8) {

@ -23,8 +23,8 @@
#include "internal.h" #include "internal.h"
#include "network.h" #include "network.h"
#include "os_support.h" #include "os_support.h"
#if HAVE_SYS_SELECT_H #if HAVE_POLL_H
#include <sys/select.h> #include <poll.h>
#endif #endif
#include <sys/time.h> #include <sys/time.h>
@ -38,9 +38,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
struct addrinfo hints, *ai, *cur_ai; struct addrinfo hints, *ai, *cur_ai;
int port, fd = -1; int port, fd = -1;
TCPContext *s = NULL; TCPContext *s = NULL;
fd_set wfds, efds; int ret;
int fd_max, ret;
struct timeval tv;
socklen_t optlen; socklen_t optlen;
char hostname[1024],proto[1024],path[1024]; char hostname[1024],proto[1024],path[1024];
char portstr[10]; char portstr[10];
@ -73,6 +71,7 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
redo: redo:
ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen); ret = connect(fd, cur_ai->ai_addr, cur_ai->ai_addrlen);
if (ret < 0) { if (ret < 0) {
struct pollfd p = {fd, POLLOUT, 0};
if (ff_neterrno() == FF_NETERROR(EINTR)) { if (ff_neterrno() == FF_NETERROR(EINTR)) {
if (url_interrupt_cb()) if (url_interrupt_cb())
goto fail1; goto fail1;
@ -88,15 +87,8 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
ret = AVERROR(EINTR); ret = AVERROR(EINTR);
goto fail1; goto fail1;
} }
fd_max = fd; ret = poll(&p, 1, 100);
FD_ZERO(&wfds); if (ret > 0)
FD_ZERO(&efds);
FD_SET(fd, &wfds);
FD_SET(fd, &efds);
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
ret = select(fd_max + 1, NULL, &wfds, &efds, &tv);
if (ret > 0 && (FD_ISSET(fd, &wfds) || FD_ISSET(fd, &efds)))
break; break;
} }
@ -140,20 +132,14 @@ static int tcp_open(URLContext *h, const char *uri, int flags)
static int tcp_read(URLContext *h, uint8_t *buf, int size) static int tcp_read(URLContext *h, uint8_t *buf, int size)
{ {
TCPContext *s = h->priv_data; TCPContext *s = h->priv_data;
int len, fd_max, ret; struct pollfd p = {s->fd, POLLIN, 0};
fd_set rfds; int len, ret;
struct timeval tv;
for (;;) { for (;;) {
if (url_interrupt_cb()) if (url_interrupt_cb())
return AVERROR(EINTR); return AVERROR(EINTR);
fd_max = s->fd; ret = poll(&p, 1, 100);
FD_ZERO(&rfds); if (ret == 1 && p.revents & POLLIN) {
FD_SET(s->fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
ret = select(fd_max + 1, &rfds, NULL, NULL, &tv);
if (ret > 0 && FD_ISSET(s->fd, &rfds)) {
len = recv(s->fd, buf, size, 0); len = recv(s->fd, buf, size, 0);
if (len < 0) { if (len < 0) {
if (ff_neterrno() != FF_NETERROR(EINTR) && if (ff_neterrno() != FF_NETERROR(EINTR) &&
@ -171,21 +157,15 @@ static int tcp_read(URLContext *h, uint8_t *buf, int size)
static int tcp_write(URLContext *h, const uint8_t *buf, int size) static int tcp_write(URLContext *h, const uint8_t *buf, int size)
{ {
TCPContext *s = h->priv_data; TCPContext *s = h->priv_data;
int ret, size1, fd_max, len; int ret, size1, len;
fd_set wfds; struct pollfd p = {s->fd, POLLOUT, 0};
struct timeval tv;
size1 = size; size1 = size;
while (size > 0) { while (size > 0) {
if (url_interrupt_cb()) if (url_interrupt_cb())
return AVERROR(EINTR); return AVERROR(EINTR);
fd_max = s->fd; ret = poll(&p, 1, 100);
FD_ZERO(&wfds); if (ret == 1 && p.revents & POLLOUT) {
FD_SET(s->fd, &wfds);
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
ret = select(fd_max + 1, NULL, &wfds, NULL, &tv);
if (ret > 0 && FD_ISSET(s->fd, &wfds)) {
len = send(s->fd, buf, size, 0); len = send(s->fd, buf, size, 0);
if (len < 0) { if (len < 0) {
if (ff_neterrno() != FF_NETERROR(EINTR) && if (ff_neterrno() != FF_NETERROR(EINTR) &&

@ -31,8 +31,8 @@
#include "internal.h" #include "internal.h"
#include "network.h" #include "network.h"
#include "os_support.h" #include "os_support.h"
#if HAVE_SYS_SELECT_H #if HAVE_POLL_H
#include <sys/select.h> #include <poll.h>
#endif #endif
#include <sys/time.h> #include <sys/time.h>
@ -432,25 +432,20 @@ static int udp_open(URLContext *h, const char *uri, int flags)
static int udp_read(URLContext *h, uint8_t *buf, int size) static int udp_read(URLContext *h, uint8_t *buf, int size)
{ {
UDPContext *s = h->priv_data; UDPContext *s = h->priv_data;
struct pollfd p = {s->udp_fd, POLLIN, 0};
int len; int len;
fd_set rfds;
int ret; int ret;
struct timeval tv;
for(;;) { for(;;) {
if (url_interrupt_cb()) if (url_interrupt_cb())
return AVERROR(EINTR); return AVERROR(EINTR);
FD_ZERO(&rfds); ret = poll(&p, 1, 100);
FD_SET(s->udp_fd, &rfds);
tv.tv_sec = 0;
tv.tv_usec = 100 * 1000;
ret = select(s->udp_fd + 1, &rfds, NULL, NULL, &tv);
if (ret < 0) { if (ret < 0) {
if (ff_neterrno() == FF_NETERROR(EINTR)) if (ff_neterrno() == FF_NETERROR(EINTR))
continue; continue;
return AVERROR(EIO); return AVERROR(EIO);
} }
if (!(ret > 0 && FD_ISSET(s->udp_fd, &rfds))) if (!(ret == 1 && p.revents & POLLIN))
continue; continue;
len = recv(s->udp_fd, buf, size, 0); len = recv(s->udp_fd, buf, size, 0);
if (len < 0) { if (len < 0) {

Loading…
Cancel
Save