/* make send-socket (dsockfd) buffer size no less * than that of read-socket (ssockfd) */ static int sync_dsockbuf_len( int ssockfd, int dsockfd ) { size_t curr_sendbuf_len = 0, curr_rcvbuf_len = 0; int rc = 0; if ( 0 != g_uopt.nosync_dbuf ) { TRACE( (void)tmfprintf( g_flog, "Must not adjust buffer size " "for send socket [%d]\n", dsockfd) ); return 0; } assert( ssockfd && dsockfd ); rc = get_sendbuf( dsockfd, &curr_sendbuf_len ); if (0 != rc) return rc; rc = get_rcvbuf( ssockfd, &curr_rcvbuf_len ); if (0 != rc) return rc; if ( curr_rcvbuf_len > curr_sendbuf_len ) { rc = set_sendbuf( dsockfd, curr_rcvbuf_len ); if (0 != rc) return rc; } return rc; }
/* set up the socket to receive multicast data * */ int setup_mcast_listener( struct sockaddr_in* sa, const struct ip_mreq* mreq, int* mcastfd, int sockbuflen ) { int sockfd, rc; int ON = 1; int buflen = sockbuflen; size_t rcvbuf_len = 0; assert( sa && mreq && mcastfd && (sockbuflen >= 0) ); TRACE( (void)tmfprintf( g_flog, "Setting up multicast listener\n") ); rc = ERR_INTERNAL; do { sockfd = socket( AF_INET, SOCK_DGRAM, 0 ); if( -1 == sockfd ) { mperror(g_flog, errno, "%s: socket", __func__); break; } if (buflen != 0) { rc = get_rcvbuf( sockfd, &rcvbuf_len ); if (0 != rc) break; if ((size_t)buflen > rcvbuf_len) { rc = set_rcvbuf( sockfd, buflen ); if (0 != rc) break; } } else { TRACE( (void)tmfprintf( g_flog, "Must not adjust buffer size " "for mcast socket [%d]\n", sockfd ) ); } rc = setsockopt( sockfd, SOL_SOCKET, SO_REUSEADDR, &ON, sizeof(ON) ); if( 0 != rc ) { mperror(g_flog, errno, "%s: setsockopt SO_REUSEADDR", __func__); break; } #ifdef SO_REUSEPORT /* On some systems (such as FreeBSD) SO_REUSEADDR just isn't enough to subscribe to N same channels for different clients. */ rc = setsockopt( sockfd, SOL_SOCKET, SO_REUSEPORT, &ON, sizeof(ON) ); if( 0 != rc ) { mperror(g_flog, errno, "%s: setsockopt SO_REUSEPORT", __func__); break; } #endif /* SO_REUSEPORT */ rc = bind( sockfd, (struct sockaddr*)sa, sizeof(*sa) ); if( 0 != rc ) { mperror(g_flog, errno, "%s: bind", __func__); break; } rc = set_multicast( sockfd, mreq, IP_ADD_MEMBERSHIP ); if( 0 != rc ) break; } while(0); if( 0 == rc ) { *mcastfd = sockfd; TRACE( (void)tmfprintf( g_flog, "Mcast listener socket=[%d] set up\n", sockfd) ); } else { (void)close(sockfd); } return rc; }