int ff_listen_bind(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h) { int ret; int reuse = 1; struct pollfd lp = { fd, POLLIN, 0 }; if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse))) { av_log(NULL, AV_LOG_WARNING, "setsockopt(SO_REUSEADDR) failed\n"); } ret = bind(fd, addr, addrlen); if (ret) return ff_neterrno(); ret = listen(fd, 1); if (ret) return ff_neterrno(); ret = ff_poll_interrupt(&lp, 1, timeout, &h->interrupt_callback); if (ret < 0) return ret; ret = accept(fd, NULL, NULL); if (ret < 0) return ff_neterrno(); closesocket(fd); ff_socket_nonblock(ret, 1); return ret; }
int ff_listen_connect(int fd, const struct sockaddr *addr, socklen_t addrlen, int timeout, URLContext *h, int will_try_next) { struct pollfd p = {fd, POLLOUT, 0}; int ret; socklen_t optlen; if (ff_socket_nonblock(fd, 1) < 0) av_log(NULL, AV_LOG_DEBUG, "ff_socket_nonblock failed\n"); while ((ret = connect(fd, addr, addrlen))) { ret = ff_neterrno(); switch (ret) { case AVERROR(EINTR): if (ff_check_interrupt(&h->interrupt_callback)) return AVERROR_EXIT; continue; case AVERROR(EINPROGRESS): case AVERROR(EAGAIN): ret = ff_poll_interrupt(&p, 1, timeout, &h->interrupt_callback); if (ret < 0) return ret; optlen = sizeof(ret); if (getsockopt (fd, SOL_SOCKET, SO_ERROR, &ret, &optlen)) ret = AVUNERROR(ff_neterrno()); if (ret != 0) { char errbuf[100]; ret = AVERROR(ret); av_strerror(ret, errbuf, sizeof(errbuf)); if (will_try_next) av_log(h, AV_LOG_WARNING, "Connection to %s failed (%s), trying next address\n", h->filename, errbuf); else av_log(h, AV_LOG_ERROR, "Connection to %s failed: %s\n", h->filename, errbuf); } default: return ret; } } return ret; }