From 87624ed9172349ee174637618a51f959de92b2e8 Mon Sep 17 00:00:00 2001 From: "Steinar H. Gunderson" Date: Sun, 17 Sep 2023 17:57:02 +0200 Subject: [PATCH] Use nonblocking srt_connect(), to allow faster abort on quit. --- nageru/video_encoder.cpp | 61 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 59 insertions(+), 2 deletions(-) diff --git a/nageru/video_encoder.cpp b/nageru/video_encoder.cpp index c1938d5..338428b 100644 --- a/nageru/video_encoder.cpp +++ b/nageru/video_encoder.cpp @@ -388,13 +388,70 @@ int VideoEncoder::connect_to_srt() return sock; } ++metric_srt_num_connection_attempts; + + // We do a non-blocking connect, so that we can check should_quit + // every now and then. + int blocking = 0; + if (srt_setsockopt(sock, 0, SRTO_RCVSYN, &blocking, sizeof(blocking)) < 0) { + fprintf(stderr, "srt_setsockopt(SRTO_SNDSYN=0): %s\n", srt_getlasterror_str()); + srt_close(sock); + continue; + } if (srt_connect(sock, cur->ai_addr, cur->ai_addrlen) < 0) { fprintf(stderr, "srt_connect(%s): %s\n", print_addrinfo(cur).c_str(), srt_getlasterror_str()); srt_close(sock); continue; } - fprintf(stderr, "Connected to destination SRT endpoint at %s.\n", print_addrinfo(cur).c_str()); - return sock; + int eid = srt_epoll_create(); + if (eid < 0) { + fprintf(stderr, "srt_epoll_create(): %s\n", srt_getlasterror_str()); + srt_close(sock); + continue; + } + int modes = SRT_EPOLL_ERR | SRT_EPOLL_OUT; + if (srt_epoll_add_usock(eid, sock, &modes) < 0) { + fprintf(stderr, "srt_epoll_usock(): %s\n", srt_getlasterror_str()); + srt_close(sock); + srt_epoll_release(eid); + continue; + } + bool ok; + while (!should_quit.load()) { + SRTSOCKET errfds[1], writefds[1]; + int num_errfds = 1, num_writefds = 1; + int poll_time_ms = 100; + int ret = srt_epoll_wait(eid, errfds, &num_errfds, writefds, &num_writefds, poll_time_ms, 0, 0, 0, 0); + if (ret < 0) { + if (srt_getlasterror(nullptr) == SRT_ETIMEOUT) { + continue; + } else { + fprintf(stderr, "srt_epoll_wait(): %s\n", srt_getlasterror_str()); + srt_close(sock); + srt_epoll_release(eid); + return -1; + } + } else if (ret > 0) { + // The SRT epoll framework is pretty odd, but seemingly, + // this is the way. Getting the same error code as srt_connect() + // would normally return seems to be impossible, though. + ok = (num_errfds == 0); + break; + fprintf(stderr, "num_errfds=%d num_writefds=%d last_err=%s\n", num_errfds, num_writefds, srt_getlasterror_str()); + break; + } + } + srt_epoll_release(eid); + if (should_quit.load()) { + srt_close(sock); + return -1; + } + if (ok) { + fprintf(stderr, "Connected to destination SRT endpoint at %s.\n", print_addrinfo(cur).c_str()); + return sock; + } else { + fprintf(stderr, "srt_connect(%s): %s\n", print_addrinfo(cur).c_str(), srt_getlasterror_str()); + srt_close(sock); + } } // Out of candidates, so give up. -- 2.39.2