| 621 | /* param is a pointer to RTP socket */ |
| 622 | |
| 623 | static void rtp_echo_thread(void* param) |
| 624 | { |
| 625 | std::vector<char> msg; |
| 626 | msg.resize(media_bufsize); |
| 627 | ssize_t nr, ns; |
| 628 | sipp_socklen_t len; |
| 629 | struct sockaddr_storage remote_rtp_addr; |
| 630 | int sock = *(int *)param; |
| 631 | |
| 632 | |
| 633 | int rc; |
| 634 | sigset_t mask; |
| 635 | sigfillset(&mask); /* Mask all allowed signals */ |
| 636 | rc = pthread_sigmask(SIG_BLOCK, &mask, nullptr); |
| 637 | if (rc) { |
| 638 | WARNING("pthread_sigmask returned %d", rc); |
| 639 | return; |
| 640 | } |
| 641 | |
| 642 | // timeout after 100ms, to enable graceful termination of the thread |
| 643 | struct timeval tv = {0, 100000}; |
| 644 | if ((setsockopt(sock, SOL_SOCKET, SO_RCVTIMEO, &tv, sizeof(tv)) < 0) || |
| 645 | (setsockopt(sock, SOL_SOCKET, SO_SNDTIMEO, &tv, sizeof(tv)) < 0)) { |
| 646 | WARNING("Cannot set socket timeout. error: %d", errno); |
| 647 | } |
| 648 | |
| 649 | while (run_echo_thread.load(std::memory_order_relaxed)) { |
| 650 | len = sizeof(remote_rtp_addr); |
| 651 | nr = recvfrom(sock, msg.data(), media_bufsize, 0, |
| 652 | (sockaddr*)&remote_rtp_addr, &len); |
| 653 | |
| 654 | if (nr < 0) { |
| 655 | if (errno == EAGAIN || errno == EWOULDBLOCK) |
| 656 | continue; |
| 657 | WARNING("%s %i", |
| 658 | "Error on RTP echo reception - stopping echo - errno=", |
| 659 | errno); |
| 660 | return; |
| 661 | } |
| 662 | if (!rtp_echo_state) { |
| 663 | continue; |
| 664 | } |
| 665 | ns = sendto(sock, msg.data(), nr, 0, |
| 666 | (sockaddr*)&remote_rtp_addr, len); |
| 667 | |
| 668 | if (ns != nr) { |
| 669 | WARNING("%s %i", |
| 670 | "Error on RTP echo transmission - stopping echo - errno=", |
| 671 | errno); |
| 672 | return; |
| 673 | } |
| 674 | |
| 675 | if (*(int*)param == media_socket_audio) { |
| 676 | rtp_pckts++; |
| 677 | rtp_bytes += ns; |
| 678 | } else { |
| 679 | /* packets on the second RTP stream */ |
| 680 | rtp2_pckts++; |