@@ -492,13 +492,69 @@ uint32_t TxFrame::extractRxqOverflow(struct msghdr *msg) {
492492 return 0 ;
493493}
494494
495+ int TxFrame::open_udp_socket_for_rx (int port, int buf_size) {
496+ int fd = ::socket (AF_INET, SOCK_DGRAM, 0 );
497+ if (fd < 0 ) {
498+ throw std::runtime_error (string_format (" Unable to open socket: %s" , std::strerror (errno)));
499+ }
500+
501+ int optval = 1 ;
502+ setsockopt (fd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof (optval));
503+
504+ // Set receive timeout to 500ms
505+ struct timeval tv;
506+ tv.tv_sec = 0 ;
507+ tv.tv_usec = 500000 ; // 500ms
508+ if (setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv)) < 0 ) {
509+ ::close (fd);
510+ throw std::runtime_error (string_format (" Unable to set socket timeout: %s" , std::strerror (errno)));
511+ }
512+
513+ if (buf_size) {
514+ if (setsockopt (fd, SOL_SOCKET, SO_RCVBUF, &buf_size, sizeof (buf_size)) < 0 ) {
515+ ::close (fd);
516+ throw std::runtime_error (string_format (" Unable to set requested buffer size: %s" , std::strerror (errno)));
517+ }
518+ int actual_buf_size = 0 ;
519+ socklen_t optlen = sizeof (actual_buf_size);
520+ getsockopt (fd, SOL_SOCKET, SO_RCVBUF, &actual_buf_size, &optlen);
521+ if (actual_buf_size < buf_size * 2 ) {
522+ // Linux doubles the value we set
523+ fprintf (stderr, " Warning: requested rx buffer size %d but got %d\n " , buf_size, actual_buf_size / 2 );
524+ }
525+ }
526+
527+ struct sockaddr_in saddr;
528+ std::memset (&saddr, 0 , sizeof (saddr));
529+ saddr.sin_family = AF_INET;
530+ saddr.sin_addr .s_addr = htonl (INADDR_ANY);
531+ saddr.sin_port = htons (static_cast <uint16_t >(port));
532+
533+ if (::bind (fd, reinterpret_cast <struct sockaddr *>(&saddr), sizeof (saddr)) < 0 ) {
534+ ::close (fd);
535+ throw std::runtime_error (string_format (" Unable to bind to port %d: %s" , port, std::strerror (errno)));
536+ }
537+
538+ return fd;
539+ }
540+
495541void TxFrame::dataSource (
496542 std::shared_ptr<Transmitter> &transmitter, std::vector<int > &rxFds, int fecTimeout, bool mirror, int logInterval) {
497543 int nfds = static_cast <int >(rxFds.size ());
498544 if (nfds <= 0 ) {
499545 throw std::runtime_error (" dataSource: no valid rx sockets" );
500546 }
501547
548+ // Set timeout on all sockets
549+ for (int fd : rxFds) {
550+ struct timeval tv;
551+ tv.tv_sec = 0 ;
552+ tv.tv_usec = 500000 ; // 500ms
553+ if (setsockopt (fd, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof (tv)) < 0 ) {
554+ throw std::runtime_error (string_format (" Unable to set socket timeout: %s" , std::strerror (errno)));
555+ }
556+ }
557+
502558 std::vector<pollfd> fds (nfds);
503559 for (int i = 0 ; i < nfds; ++i) {
504560 fds[i].fd = rxFds[i];
@@ -650,7 +706,8 @@ void TxFrame::dataSource(
650706
651707 ssize_t rsize = ::recvmsg (pfd.fd , &msg, 0 );
652708 if (rsize < 0 ) {
653- if (errno != EWOULDBLOCK && errno != EAGAIN) {
709+ if (errno != EWOULDBLOCK && errno != EAGAIN && errno != ETIMEDOUT) {
710+ continue ;
654711 throw std::runtime_error (string_format (" Error receiving packet: %s" , std::strerror (errno)));
655712 }
656713 break ;
@@ -809,7 +866,7 @@ void TxFrame::run(Rtl8812aDevice *rtlDevice, TxArgs *arg) {
809866 // Attempt to create a UDP listening socket
810867 std::vector<int > rxFds;
811868 int bindPort = arg->udp_port ;
812- int udpFd = open_udp_socket_for_rx (bindPort, arg->rcv_buf );
869+ int udpFd = TxFrame:: open_udp_socket_for_rx (bindPort, arg->rcv_buf );
813870
814871 if (arg->udp_port == 0 ) {
815872 // ephemeral port
0 commit comments