Add DSCP support for POSIX platforms. This CL only includes the necessary changes in PhysicalSocketServer, and doesn't include the Java or Objective C API. Note that this is doing exactly the same thing as UDPSocketPosix in chromium. BUG=webrtc:5658 Change-Id: I295455eaccba2a83cdd1bc55848f325c310f8d32 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/168260 Reviewed-by: Harald Alvestrand <hta@webrtc.org> Reviewed-by: Qingsi Wang <qingsi@webrtc.org> Commit-Queue: Taylor <deadbeef@webrtc.org> Cr-Commit-Position: refs/heads/master@{#30478}
diff --git a/rtc_base/physical_socket_server.cc b/rtc_base/physical_socket_server.cc index bd6a324..08947e1 100644 --- a/rtc_base/physical_socket_server.cc +++ b/rtc_base/physical_socket_server.cc
@@ -140,6 +140,7 @@ Close(); s_ = ::socket(family, type, 0); udp_ = (SOCK_DGRAM == type); + family_ = family; UpdateLastError(); if (udp_) { SetEnabledEvents(DE_READ | DE_WRITE); @@ -289,10 +290,18 @@ return -1; socklen_t optlen = sizeof(*value); int ret = ::getsockopt(s_, slevel, sopt, (SockOptArg)value, &optlen); - if (ret != -1 && opt == OPT_DONTFRAGMENT) { + if (ret == -1) { + return -1; + } + if (opt == OPT_DONTFRAGMENT) { #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) *value = (*value != IP_PMTUDISC_DONT) ? 1 : 0; #endif + } else if (opt == OPT_DSCP) { +#if defined(WEBRTC_POSIX) + // unshift DSCP value to get six most significant bits of IP DiffServ field + *value >>= 2; +#endif } return ret; } @@ -306,7 +315,18 @@ #if defined(WEBRTC_LINUX) && !defined(WEBRTC_ANDROID) value = (value) ? IP_PMTUDISC_DO : IP_PMTUDISC_DONT; #endif + } else if (opt == OPT_DSCP) { +#if defined(WEBRTC_POSIX) + // shift DSCP value to fit six most significant bits of IP DiffServ field + value <<= 2; +#endif } +#if defined(WEBRTC_POSIX) + if (sopt == IPV6_TCLASS) { + // Set the IPv4 option in all cases to support dual-stack sockets. + ::setsockopt(s_, IPPROTO_IP, IP_TOS, (SockOptArg)&value, sizeof(value)); + } +#endif return ::setsockopt(s_, slevel, sopt, (SockOptArg)&value, sizeof(value)); } @@ -554,8 +574,19 @@ *sopt = TCP_NODELAY; break; case OPT_DSCP: +#if defined(WEBRTC_POSIX) + if (family_ == AF_INET6) { + *slevel = IPPROTO_IPV6; + *sopt = IPV6_TCLASS; + } else { + *slevel = IPPROTO_IP; + *sopt = IP_TOS; + } + break; +#else RTC_LOG(LS_WARNING) << "Socket::OPT_DSCP not supported."; return -1; +#endif case OPT_RTP_SENDTIME_EXTN_ID: return -1; // No logging is necessary as this not a OS socket option. default:
diff --git a/rtc_base/physical_socket_server.h b/rtc_base/physical_socket_server.h index e85b2b0..a71810f 100644 --- a/rtc_base/physical_socket_server.h +++ b/rtc_base/physical_socket_server.h
@@ -199,11 +199,12 @@ virtual void EnableEvents(uint8_t events); virtual void DisableEvents(uint8_t events); - static int TranslateOption(Option opt, int* slevel, int* sopt); + int TranslateOption(Option opt, int* slevel, int* sopt); PhysicalSocketServer* ss_; SOCKET s_; bool udp_; + int family_ = 0; CriticalSection crit_; int error_ RTC_GUARDED_BY(crit_); ConnState state_;
diff --git a/rtc_base/socket_unittest.cc b/rtc_base/socket_unittest.cc index 2af3a8e..6ea4b47 100644 --- a/rtc_base/socket_unittest.cc +++ b/rtc_base/socket_unittest.cc
@@ -1027,6 +1027,15 @@ int current_nd, desired_nd = 1; ASSERT_EQ(-1, socket->GetOption(Socket::OPT_NODELAY, ¤t_nd)); ASSERT_EQ(-1, socket->SetOption(Socket::OPT_NODELAY, desired_nd)); + +#if defined(WEBRTC_POSIX) + // Check DSCP. + int current_dscp, desired_dscp = 1; + ASSERT_NE(-1, socket->GetOption(Socket::OPT_DSCP, ¤t_dscp)); + ASSERT_NE(-1, socket->SetOption(Socket::OPT_DSCP, desired_dscp)); + ASSERT_NE(-1, socket->GetOption(Socket::OPT_DSCP, ¤t_dscp)); + ASSERT_EQ(desired_dscp, current_dscp); +#endif } void SocketTest::SocketRecvTimestamp(const IPAddress& loopback) {