@@ -289,6 +289,20 @@ void srt::CChannel::attach(UDPSOCKET udpsock, const sockaddr_any& udpsocks_addr)
289289 setUDPSockOpt ();
290290}
291291
292+ static inline string fmt_opt (bool value, const string& label)
293+ {
294+ string out;
295+ out.reserve (label.size () + 2 );
296+ out = value ? " +" : " -" ;
297+ out += label;
298+ return out;
299+ }
300+
301+ static inline string fmt_alt (bool value, const string& label, const string& unlabel)
302+ {
303+ return value ? label : unlabel;
304+ }
305+
292306void srt::CChannel::setUDPSockOpt ()
293307{
294308#if defined(SUNOS)
@@ -297,13 +311,13 @@ void srt::CChannel::setUDPSockOpt()
297311 // Retrieve starting SND/RCV Buffer sizes.
298312 int startRCVBUF = 0 ;
299313 optSize = sizeof (startRCVBUF);
300- if (0 ! = ::getsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (void *)&startRCVBUF, &optSize))
314+ if (- 1 = = ::getsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (void *)&startRCVBUF, &optSize))
301315 {
302316 startRCVBUF = -1 ;
303317 }
304318 int startSNDBUF = 0 ;
305319 optSize = sizeof (startSNDBUF);
306- if (0 ! = ::getsockopt (m_iSocket, SOL_SOCKET, SO_SNDBUF, (void *)&startSNDBUF, &optSize))
320+ if (- 1 = = ::getsockopt (m_iSocket, SOL_SOCKET, SO_SNDBUF, (void *)&startSNDBUF, &optSize))
307321 {
308322 startSNDBUF = -1 ;
309323 }
@@ -312,13 +326,12 @@ void srt::CChannel::setUDPSockOpt()
312326 // maximum value.
313327 // However, do not reduce the buffer size.
314328 const int maxsize = 64000 ;
315- if (0 !=
316- ::setsockopt (
317- m_iSocket, SOL_SOCKET, SO_RCVBUF, (const char *)&m_mcfg.iUDPRcvBufSize, sizeof m_mcfg.iUDPRcvBufSize))
329+ if (-1 == ::setsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF,
330+ (const char *)&m_mcfg.iUDPRcvBufSize , sizeof m_mcfg.iUDPRcvBufSize ))
318331 {
319332 int currentRCVBUF = 0 ;
320333 optSize = sizeof (currentRCVBUF);
321- if (0 ! = ::getsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (void *)¤tRCVBUF, &optSize))
334+ if (- 1 = = ::getsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (void *)¤tRCVBUF, &optSize))
322335 {
323336 currentRCVBUF = -1 ;
324337 }
@@ -327,13 +340,12 @@ void srt::CChannel::setUDPSockOpt()
327340 ::setsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (const char *)&maxsize, sizeof maxsize);
328341 }
329342 }
330- if (0 !=
331- ::setsockopt (
332- m_iSocket, SOL_SOCKET, SO_SNDBUF, (const char *)&m_mcfg.iUDPSndBufSize, sizeof m_mcfg.iUDPSndBufSize))
343+ if (-1 == ::setsockopt (m_iSocket, SOL_SOCKET, SO_SNDBUF,
344+ (const char *)&m_mcfg.iUDPSndBufSize , sizeof m_mcfg.iUDPSndBufSize ))
333345 {
334346 int currentSNDBUF = 0 ;
335347 optSize = sizeof (currentSNDBUF);
336- if (0 ! = ::getsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (void *)¤tSNDBUF, &optSize))
348+ if (- 1 = = ::getsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (void *)¤tSNDBUF, &optSize))
337349 {
338350 currentSNDBUF = -1 ;
339351 }
@@ -346,13 +358,13 @@ void srt::CChannel::setUDPSockOpt()
346358 // Retrieve ending SND/RCV Buffer sizes.
347359 int endRCVBUF = 0 ;
348360 optSize = sizeof (endRCVBUF);
349- if (0 ! = ::getsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (void *)&endRCVBUF, &optSize))
361+ if (- 1 = = ::getsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (void *)&endRCVBUF, &optSize))
350362 {
351363 endRCVBUF = -1 ;
352364 }
353365 int endSNDBUF = 0 ;
354366 optSize = sizeof (endSNDBUF);
355- if (0 ! = ::getsockopt (m_iSocket, SOL_SOCKET, SO_SNDBUF, (void *)&endSNDBUF, &optSize))
367+ if (- 1 = = ::getsockopt (m_iSocket, SOL_SOCKET, SO_SNDBUF, (void *)&endSNDBUF, &optSize))
356368 {
357369 endSNDBUF = -1 ;
358370 }
@@ -368,90 +380,137 @@ void srt::CChannel::setUDPSockOpt()
368380#elif defined(BSD) || TARGET_OS_MAC
369381 // BSD system will fail setsockopt if the requested buffer size exceeds system maximum value
370382 int maxsize = 64000 ;
371- if (0 ! = ::setsockopt (
383+ if (- 1 = = ::setsockopt (
372384 m_iSocket, SOL_SOCKET, SO_RCVBUF, (const char *)&m_mcfg.iUDPRcvBufSize , sizeof m_mcfg.iUDPRcvBufSize ))
373385 ::setsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF, (const char *)&maxsize, sizeof maxsize);
374- if (0 ! = ::setsockopt (
386+ if (- 1 = = ::setsockopt (
375387 m_iSocket, SOL_SOCKET, SO_SNDBUF, (const char *)&m_mcfg.iUDPSndBufSize , sizeof m_mcfg.iUDPSndBufSize ))
376388 ::setsockopt (m_iSocket, SOL_SOCKET, SO_SNDBUF, (const char *)&maxsize, sizeof maxsize);
377389#else
378390 // for other systems, if requested is greated than maximum, the maximum value will be automactally used
379- if ((0 !=
380- ::setsockopt (
381- m_iSocket, SOL_SOCKET, SO_RCVBUF, ( const char *)&m_mcfg.iUDPRcvBufSize, sizeof m_mcfg.iUDPRcvBufSize)) ||
382- (0 != ::setsockopt(
383- m_iSocket, SOL_SOCKET, SO_SNDBUF, (const char *)&m_mcfg.iUDPSndBufSize, sizeof m_mcfg.iUDPSndBufSize)))
391+ if ((- 1 == :: setsockopt (m_iSocket, SOL_SOCKET, SO_RCVBUF,
392+ ( const char *)&m_mcfg. iUDPRcvBufSize , sizeof m_mcfg. iUDPRcvBufSize ))
393+ ||
394+ (- 1 == ::setsockopt ( m_iSocket, SOL_SOCKET, SO_SNDBUF,
395+ (const char *)&m_mcfg.iUDPSndBufSize , sizeof m_mcfg.iUDPSndBufSize )))
384396 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
385397#endif
386398
399+ bool is_set = false ;
400+ bool adr_unspec = false , adr_mapped = false , adr_v6 = false ;
401+ if (m_BindAddr.family () == AF_INET)
402+ {
403+ adr_unspec = m_BindAddr.isany ();
404+ }
405+ else
406+ {
407+ adr_unspec = IN6_IS_ADDR_UNSPECIFIED (&m_BindAddr.sin6 .sin6_addr );
408+ adr_mapped = IN6_IS_ADDR_V4MAPPED (&m_BindAddr.sin6 .sin6_addr );
409+ adr_v6 = true ;
410+ }
411+
387412 if (m_mcfg.iIpTTL != -1 )
388413 {
389- if (m_BindAddr. family () == AF_INET )
414+ if (!adr_v6 )
390415 {
391- if (0 != ::setsockopt (m_iSocket, IPPROTO_IP, IP_TTL, (const char *)&m_mcfg.iIpTTL , sizeof m_mcfg.iIpTTL ))
416+ if (-1 == ::setsockopt (m_iSocket, IPPROTO_IP, IP_TTL, (const char *)&m_mcfg.iIpTTL , sizeof m_mcfg.iIpTTL ))
417+ {
418+ LOGC (kmlog.Error , log << " setsockopt(IP_TTL): " << SysStrError (NET_ERROR));
392419 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
420+ }
421+ is_set = true ;
393422 }
394423 else
395424 {
396425 // If IPv6 address is unspecified, set BOTH IP_TTL and IPV6_UNICAST_HOPS.
397426
398427 // For specified IPv6 address, set IPV6_UNICAST_HOPS ONLY UNLESS it's an IPv4-mapped-IPv6
399- if (IN6_IS_ADDR_UNSPECIFIED (&m_BindAddr.sin6 .sin6_addr ) ||
400- !IN6_IS_ADDR_V4MAPPED (&m_BindAddr.sin6 .sin6_addr ))
428+ if (adr_unspec || !adr_mapped)
401429 {
402- if (0 !=
403- ::setsockopt (
404- m_iSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS, (const char *)&m_mcfg.iIpTTL, sizeof m_mcfg.iIpTTL))
430+ if (-1 == ::setsockopt ( m_iSocket, IPPROTO_IPV6, IPV6_UNICAST_HOPS,
431+ (const char *)&m_mcfg.iIpTTL , sizeof m_mcfg.iIpTTL ))
405432 {
433+ LOGC (kmlog.Error , log << " setsockopt(IPV6_UNICAST_HOPS): " << SysStrError (NET_ERROR));
406434 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
407435 }
436+ is_set = true ;
408437 }
409438 // For specified IPv6 address, set IP_TTL ONLY WHEN it's an IPv4-mapped-IPv6
410- if (IN6_IS_ADDR_UNSPECIFIED (&m_BindAddr. sin6 . sin6_addr ) || IN6_IS_ADDR_V4MAPPED (&m_BindAddr. sin6 . sin6_addr ) )
439+ if (!is_set) // adr_mapped (because adr_unspec was handled above )
411440 {
412- if (0 ! = ::setsockopt (m_iSocket, IPPROTO_IP, IP_TTL, (const char *)&m_mcfg.iIpTTL , sizeof m_mcfg.iIpTTL ))
441+ if (- 1 = = ::setsockopt (m_iSocket, IPPROTO_IP, IP_TTL, (const char *)&m_mcfg.iIpTTL , sizeof m_mcfg.iIpTTL ))
413442 {
443+ LOGC (kmlog.Error , log << " setsockopt(IP_TTL): " << SysStrError (NET_ERROR)
444+ << fmt_alt (adr_unspec, " (v6 unspec)" , " (v6 mapped v4)" ));
414445 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
415446 }
447+ is_set = true ;
416448 }
417449 }
450+
451+ if (!is_set)
452+ {
453+ LOGC (kmlog.Error , log << " srt_setsockflag(SRTO_IPTTL): No suitable condition for adr=" << m_BindAddr.str ()
454+ << " : " << fmt_opt (adr_v6, " v6 " ) << fmt_opt (adr_unspec, " unspec " ) << fmt_opt (adr_mapped, " mapped" ));
455+ throw CUDTException (MJ_SETUP, MN_INVAL, 0 );
456+ }
418457 }
419458
459+ is_set = false ;
420460 if (m_mcfg.iIpToS != -1 )
421461 {
422462 if (m_BindAddr.family () == AF_INET)
423463 {
424- if (0 != ::setsockopt (m_iSocket, IPPROTO_IP, IP_TOS, (const char *)&m_mcfg.iIpToS , sizeof m_mcfg.iIpToS ))
464+ if (-1 == ::setsockopt (m_iSocket, IPPROTO_IP, IP_TOS, (const char *)&m_mcfg.iIpToS , sizeof m_mcfg.iIpToS ))
465+ {
466+ LOGC (kmlog.Error , log << " setsockopt(IP_TOS): " << SysStrError (NET_ERROR));
425467 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
468+ }
469+ is_set = true ;
426470 }
427471 else
428472 {
429473 // If IPv6 address is unspecified, set BOTH IP_TOS and IPV6_TCLASS.
430474
475+ SRT_ATR_UNUSED bool using_tclass = false ;
431476#ifdef IPV6_TCLASS
477+ using_tclass = true ;
432478 // For specified IPv6 address, set IPV6_TCLASS ONLY UNLESS it's an IPv4-mapped-IPv6
433- if (IN6_IS_ADDR_UNSPECIFIED (&m_BindAddr.sin6 .sin6_addr ) ||
434- !IN6_IS_ADDR_V4MAPPED (&m_BindAddr.sin6 .sin6_addr ))
479+ if (adr_unspec || !adr_mapped)
435480 {
436- if (0 != ::setsockopt (
437- m_iSocket, IPPROTO_IPV6, IPV6_TCLASS, (const char *)&m_mcfg.iIpToS , sizeof m_mcfg.iIpToS ))
481+ if (- 1 == ::setsockopt (m_iSocket, IPPROTO_IPV6, IPV6_TCLASS,
482+ (const char *)&m_mcfg.iIpToS , sizeof m_mcfg.iIpToS ))
438483 {
484+ LOGC (kmlog.Error , log << " setsockopt(IPV6_TCLASS): " << SysStrError (NET_ERROR));
439485 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
440486 }
487+ is_set = true ;
441488 }
442489#endif
443490
444491 // For specified IPv6 address, set IP_TOS ONLY WHEN it's an IPv4-mapped-IPv6
445- if (IN6_IS_ADDR_UNSPECIFIED (&m_BindAddr. sin6 . sin6_addr ) || IN6_IS_ADDR_V4MAPPED (&m_BindAddr. sin6 . sin6_addr ))
492+ if (!is_set && (adr_unspec || adr_mapped ))
446493 {
447- if (0 ! = ::setsockopt (m_iSocket, IPPROTO_IP, IP_TOS, (const char *)&m_mcfg.iIpToS , sizeof m_mcfg.iIpToS ))
494+ if (- 1 = = ::setsockopt (m_iSocket, IPPROTO_IP, IP_TOS, (const char *)&m_mcfg.iIpToS , sizeof m_mcfg.iIpToS ))
448495 {
496+ LOGC (kmlog.Error , log << " setsockopt(IP_TOS): " << SysStrError (NET_ERROR)
497+ << (adr_unspec ? " (v6 unspecified)" : " (v6 mapped v4)" )
498+ << (using_tclass ? " (fallback to IP_TOS)" : " " ));
449499 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
450500 }
501+ is_set = true ;
451502 }
452503 }
504+
505+ if (!is_set)
506+ {
507+ LOGC (kmlog.Error , log << " srt_setsockflag(SRTO_IPTOS): No suitable condition for adr=" << m_BindAddr.str ()
508+ << " : " << fmt_opt (adr_v6, " v6 " ) << fmt_opt (adr_unspec, " unspec " ) << fmt_opt (adr_mapped, " mapped" ));
509+ throw CUDTException (MJ_SETUP, MN_INVAL, 0 );
510+ }
453511 }
454512
513+
455514#ifdef SRT_ENABLE_BINDTODEVICE
456515 if (!m_mcfg.sBindToDevice .empty ())
457516 {
@@ -461,14 +520,10 @@ void srt::CChannel::setUDPSockOpt()
461520 throw CUDTException (MJ_NOTSUP, MN_INVAL, 0 );
462521 }
463522
464- if (0 != ::setsockopt (
465- m_iSocket, SOL_SOCKET, SO_BINDTODEVICE, m_mcfg.sBindToDevice .c_str (), m_mcfg.sBindToDevice .size ()))
523+ if (- 1 == ::setsockopt (m_iSocket, SOL_SOCKET, SO_BINDTODEVICE,
524+ m_mcfg.sBindToDevice .c_str (), m_mcfg.sBindToDevice .size ()))
466525 {
467- #if ENABLE_LOGGING
468- char buf[255 ];
469- const char * err = SysStrError (NET_ERROR, buf, 255 );
470- LOGC (kmlog.Error , log << " setsockopt(SRTO_BINDTODEVICE): " << err);
471- #endif // ENABLE_LOGGING
526+ LOGC (kmlog.Error , log << " setsockopt(SRTO_BINDTODEVICE): " << SysStrError (NET_ERROR));
472527 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
473528 }
474529 }
@@ -482,7 +537,7 @@ void srt::CChannel::setUDPSockOpt()
482537 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
483538#elif defined(_WIN32)
484539 u_long nonBlocking = 1 ;
485- if (0 ! = ioctlsocket (m_iSocket, FIONBIO, &nonBlocking))
540+ if (- 1 = = ioctlsocket (m_iSocket, FIONBIO, &nonBlocking))
486541 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
487542#else
488543 timeval tv;
@@ -495,7 +550,7 @@ void srt::CChannel::setUDPSockOpt()
495550 tv.tv_usec = 100 ;
496551#endif
497552 // Set receiving time-out value
498- if (0 ! = ::setsockopt (m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof (timeval)))
553+ if (- 1 = = ::setsockopt (m_iSocket, SOL_SOCKET, SO_RCVTIMEO, (char *)&tv, sizeof (timeval)))
499554 throw CUDTException (MJ_SETUP, MN_NORES, NET_ERROR);
500555#endif
501556
0 commit comments