diff --git a/rtc_base/virtual_socket_server.cc b/rtc_base/virtual_socket_server.cc index 88c6eb9fc5..5d36e3e1de 100644 --- a/rtc_base/virtual_socket_server.cc +++ b/rtc_base/virtual_socket_server.cc @@ -588,12 +588,15 @@ uint16_t VirtualSocketServer::GetNextPort() { } void VirtualSocketServer::SetSendingBlocked(bool blocked) { - if (blocked == sending_blocked_) { - // Unchanged; nothing to do. - return; + { + webrtc::MutexLock lock(&mutex_); + if (blocked == sending_blocked_) { + // Unchanged; nothing to do. + return; + } + sending_blocked_ = blocked; } - sending_blocked_ = blocked; - if (!sending_blocked_) { + if (!blocked) { // Sending was blocked, but is now unblocked. This signal gives sockets a // chance to fire SignalWriteEvent, and for TCP, send buffered data. SignalReadyToSend(); @@ -877,31 +880,27 @@ int VirtualSocketServer::SendUdp(VirtualSocket* socket, const char* data, size_t data_size, const SocketAddress& remote_addr) { - ++sent_packets_; - if (sending_blocked_) { - socket->SetToBlocked(); - return -1; - } - - if (data_size > largest_seen_udp_payload_) { - if (data_size > 1000) { - RTC_LOG(LS_VERBOSE) << "Largest UDP seen is " << data_size; + { + webrtc::MutexLock lock(&mutex_); + ++sent_packets_; + if (sending_blocked_) { + socket->SetToBlocked(); + return -1; } - largest_seen_udp_payload_ = data_size; - } - // See if we want to drop this packet. - if (data_size > max_udp_payload_) { - RTC_LOG(LS_VERBOSE) << "Dropping too large UDP payload of size " - << data_size << ", UDP payload limit is " - << max_udp_payload_; - // Return as if send was successful; packet disappears. - return data_size; - } + // See if we want to drop this packet. + if (data_size > max_udp_payload_) { + RTC_LOG(LS_VERBOSE) << "Dropping too large UDP payload of size " + << data_size << ", UDP payload limit is " + << max_udp_payload_; + // Return as if send was successful; packet disappears. + return data_size; + } - if (Random() < drop_prob_) { - RTC_LOG(LS_VERBOSE) << "Dropping packet: bad luck"; - return static_cast(data_size); + if (Random() < drop_prob_) { + RTC_LOG(LS_VERBOSE) << "Dropping packet: bad luck"; + return static_cast(data_size); + } } VirtualSocket* recipient = LookupBinding(remote_addr); @@ -938,11 +937,13 @@ int VirtualSocketServer::SendUdp(VirtualSocket* socket, // NOTE: There are better algorithms for maintaining such a queue (such as // "Derivative Random Drop"); however, this algorithm is a more accurate // simulation of what a normal network would do. - - size_t packet_size = data_size + UDP_HEADER_SIZE; - if (network_size + packet_size > network_capacity_) { - RTC_LOG(LS_VERBOSE) << "Dropping packet: network capacity exceeded"; - return static_cast(data_size); + { + webrtc::MutexLock lock(&mutex_); + size_t packet_size = data_size + UDP_HEADER_SIZE; + if (network_size + packet_size > network_capacity_) { + RTC_LOG(LS_VERBOSE) << "Dropping packet: network capacity exceeded"; + return static_cast(data_size); + } } AddPacketToNetwork(socket, recipient, cur_time, data, data_size, @@ -953,11 +954,14 @@ int VirtualSocketServer::SendUdp(VirtualSocket* socket, } void VirtualSocketServer::SendTcp(VirtualSocket* socket) { - ++sent_packets_; - if (sending_blocked_) { - // Eventually the socket's buffer will fill and VirtualSocket::SendTcp will - // set EWOULDBLOCK. - return; + { + webrtc::MutexLock lock(&mutex_); + ++sent_packets_; + if (sending_blocked_) { + // Eventually the socket's buffer will fill and VirtualSocket::SendTcp + // will set EWOULDBLOCK. + return; + } } // TCP can't send more data than will fill up the receiver's buffer. @@ -978,7 +982,7 @@ void VirtualSocketServer::SendTcp(VirtualSocket* socket) { socket->PurgeNetworkPackets(cur_time); while (true) { - size_t available = recv_buffer_capacity_ - recipient->recv_buffer_size(); + size_t available = recv_buffer_capacity() - recipient->recv_buffer_size(); size_t max_data_size = std::min(available, TCP_MSS - TCP_HEADER_SIZE); size_t data_size = std::min(socket->send_buffer_size(), max_data_size); @@ -991,7 +995,7 @@ void VirtualSocketServer::SendTcp(VirtualSocket* socket) { socket->UpdateSend(data_size); } - socket->MaybeSignalWriteEvent(send_buffer_capacity_); + socket->MaybeSignalWriteEvent(send_buffer_capacity()); } void VirtualSocketServer::SendTcp(const SocketAddress& addr) { @@ -1032,6 +1036,7 @@ void VirtualSocketServer::AddPacketToNetwork(VirtualSocket* sender, } uint32_t VirtualSocketServer::SendDelay(uint32_t size) { + webrtc::MutexLock lock(&mutex_); if (bandwidth_ == 0) return 0; else @@ -1060,6 +1065,7 @@ void PrintFunction(std::vector >* f) { #endif // void VirtualSocketServer::UpdateDelayDistribution() { + webrtc::MutexLock lock(&mutex_); delay_dist_ = CreateDistribution(delay_mean_, delay_stddev_, delay_samples_); } @@ -1245,4 +1251,62 @@ void VirtualSocketServer::SetDefaultSourceAddress(const IPAddress& from_addr) { } } +void VirtualSocketServer::set_bandwidth(uint32_t bandwidth) { + webrtc::MutexLock lock(&mutex_); + bandwidth_ = bandwidth; +} +void VirtualSocketServer::set_network_capacity(uint32_t capacity) { + webrtc::MutexLock lock(&mutex_); + network_capacity_ = capacity; +} + +uint32_t VirtualSocketServer::send_buffer_capacity() const { + webrtc::MutexLock lock(&mutex_); + return send_buffer_capacity_; +} +void VirtualSocketServer::set_send_buffer_capacity(uint32_t capacity) { + webrtc::MutexLock lock(&mutex_); + send_buffer_capacity_ = capacity; +} + +uint32_t VirtualSocketServer::recv_buffer_capacity() const { + webrtc::MutexLock lock(&mutex_); + return recv_buffer_capacity_; +} +void VirtualSocketServer::set_recv_buffer_capacity(uint32_t capacity) { + webrtc::MutexLock lock(&mutex_); + recv_buffer_capacity_ = capacity; +} + +void VirtualSocketServer::set_delay_mean(uint32_t delay_mean) { + webrtc::MutexLock lock(&mutex_); + delay_mean_ = delay_mean; +} +void VirtualSocketServer::set_delay_stddev(uint32_t delay_stddev) { + webrtc::MutexLock lock(&mutex_); + delay_stddev_ = delay_stddev; +} +void VirtualSocketServer::set_delay_samples(uint32_t delay_samples) { + webrtc::MutexLock lock(&mutex_); + delay_samples_ = delay_samples; +} + +void VirtualSocketServer::set_drop_probability(double drop_prob) { + RTC_DCHECK_GE(drop_prob, 0.0); + RTC_DCHECK_LE(drop_prob, 1.0); + + webrtc::MutexLock lock(&mutex_); + drop_prob_ = drop_prob; +} + +void VirtualSocketServer::set_max_udp_payload(size_t payload_size) { + webrtc::MutexLock lock(&mutex_); + max_udp_payload_ = payload_size; +} + +uint32_t VirtualSocketServer::sent_packets() const { + webrtc::MutexLock lock(&mutex_); + return sent_packets_; +} + } // namespace rtc diff --git a/rtc_base/virtual_socket_server.h b/rtc_base/virtual_socket_server.h index 77ddb76d72..8873f18dcc 100644 --- a/rtc_base/virtual_socket_server.h +++ b/rtc_base/virtual_socket_server.h @@ -172,60 +172,39 @@ class VirtualSocketServer : public SocketServer { // Limits the network bandwidth (maximum bytes per second). Zero means that // all sends occur instantly. Defaults to 0. - uint32_t bandwidth() const { return bandwidth_; } - void set_bandwidth(uint32_t bandwidth) { bandwidth_ = bandwidth; } + void set_bandwidth(uint32_t bandwidth) RTC_LOCKS_EXCLUDED(mutex_); // Limits the amount of data which can be in flight on the network without // packet loss (on a per sender basis). Defaults to 64 KB. - uint32_t network_capacity() const { return network_capacity_; } - void set_network_capacity(uint32_t capacity) { network_capacity_ = capacity; } + void set_network_capacity(uint32_t capacity) RTC_LOCKS_EXCLUDED(mutex_); // The amount of data which can be buffered by tcp on the sender's side - uint32_t send_buffer_capacity() const { return send_buffer_capacity_; } - void set_send_buffer_capacity(uint32_t capacity) { - send_buffer_capacity_ = capacity; - } + uint32_t send_buffer_capacity() const RTC_LOCKS_EXCLUDED(mutex_); + void set_send_buffer_capacity(uint32_t capacity) RTC_LOCKS_EXCLUDED(mutex_); // The amount of data which can be buffered by tcp on the receiver's side - uint32_t recv_buffer_capacity() const { return recv_buffer_capacity_; } - void set_recv_buffer_capacity(uint32_t capacity) { - recv_buffer_capacity_ = capacity; - } + uint32_t recv_buffer_capacity() const RTC_LOCKS_EXCLUDED(mutex_); + void set_recv_buffer_capacity(uint32_t capacity) RTC_LOCKS_EXCLUDED(mutex_); // Controls the (transit) delay for packets sent in the network. This does // not inclue the time required to sit in the send queue. Both of these // values are measured in milliseconds. Defaults to no delay. - uint32_t delay_mean() const { return delay_mean_; } - uint32_t delay_stddev() const { return delay_stddev_; } - uint32_t delay_samples() const { return delay_samples_; } - void set_delay_mean(uint32_t delay_mean) { delay_mean_ = delay_mean; } - void set_delay_stddev(uint32_t delay_stddev) { delay_stddev_ = delay_stddev; } - void set_delay_samples(uint32_t delay_samples) { - delay_samples_ = delay_samples; - } + void set_delay_mean(uint32_t delay_mean) RTC_LOCKS_EXCLUDED(mutex_); + void set_delay_stddev(uint32_t delay_stddev) RTC_LOCKS_EXCLUDED(mutex_); + void set_delay_samples(uint32_t delay_samples) RTC_LOCKS_EXCLUDED(mutex_); // If the (transit) delay parameters are modified, this method should be // called to recompute the new distribution. - void UpdateDelayDistribution(); + void UpdateDelayDistribution() RTC_LOCKS_EXCLUDED(mutex_); // Controls the (uniform) probability that any sent packet is dropped. This // is separate from calculations to drop based on queue size. - double drop_probability() { return drop_prob_; } - void set_drop_probability(double drop_prob) { - RTC_DCHECK_GE(drop_prob, 0.0); - RTC_DCHECK_LE(drop_prob, 1.0); - drop_prob_ = drop_prob; - } + void set_drop_probability(double drop_prob) RTC_LOCKS_EXCLUDED(mutex_); // Controls the maximum UDP payload for the networks simulated // by this server. Any UDP payload sent that is larger than this will // be dropped. - size_t max_udp_payload() { return max_udp_payload_; } - void set_max_udp_payload(size_t payload_size) { - max_udp_payload_ = payload_size; - } - - size_t largest_seen_udp_payload() { return largest_seen_udp_payload_; } + void set_max_udp_payload(size_t payload_size) RTC_LOCKS_EXCLUDED(mutex_); // If `blocked` is true, subsequent attempts to send will result in -1 being // returned, with the socket error set to EWOULDBLOCK. @@ -235,7 +214,7 @@ class VirtualSocketServer : public SocketServer { // // This can be used to simulate the send buffer on a network interface being // full, and test functionality related to EWOULDBLOCK/SignalWriteEvent. - void SetSendingBlocked(bool blocked); + void SetSendingBlocked(bool blocked) RTC_LOCKS_EXCLUDED(mutex_); // SocketFactory: VirtualSocket* CreateSocket(int family, int type) override; @@ -281,7 +260,7 @@ class VirtualSocketServer : public SocketServer { // Number of packets that clients have attempted to send through this virtual // socket server. Intended to be used for test assertions. - uint32_t sent_packets() const { return sent_packets_; } + uint32_t sent_packets() const RTC_LOCKS_EXCLUDED(mutex_); // Assign IP and Port if application's address is unspecified. Also apply // `alternative_address_mapping_`. @@ -319,13 +298,13 @@ class VirtualSocketServer : public SocketServer { const SocketAddress& remote_addr); // Moves as much data as possible from the sender's buffer to the network - void SendTcp(VirtualSocket* socket); + void SendTcp(VirtualSocket* socket) RTC_LOCKS_EXCLUDED(mutex_); // Like above, but lookup sender by address. - void SendTcp(const SocketAddress& addr); + void SendTcp(const SocketAddress& addr) RTC_LOCKS_EXCLUDED(mutex_); // Computes the number of milliseconds required to send a packet of this size. - uint32_t SendDelay(uint32_t size); + uint32_t SendDelay(uint32_t size) RTC_LOCKS_EXCLUDED(mutex_); // Cancel attempts to connect to a socket that is being closed. void CancelConnects(VirtualSocket* socket); @@ -416,30 +395,30 @@ class VirtualSocketServer : public SocketServer { IPAddress default_source_address_v4_; IPAddress default_source_address_v6_; - uint32_t bandwidth_; - uint32_t network_capacity_; - uint32_t send_buffer_capacity_; - uint32_t recv_buffer_capacity_; - uint32_t delay_mean_; - uint32_t delay_stddev_; - uint32_t delay_samples_; + mutable webrtc::Mutex mutex_; + + uint32_t bandwidth_ RTC_GUARDED_BY(mutex_); + uint32_t network_capacity_ RTC_GUARDED_BY(mutex_); + uint32_t send_buffer_capacity_ RTC_GUARDED_BY(mutex_); + uint32_t recv_buffer_capacity_ RTC_GUARDED_BY(mutex_); + uint32_t delay_mean_ RTC_GUARDED_BY(mutex_); + uint32_t delay_stddev_ RTC_GUARDED_BY(mutex_); + uint32_t delay_samples_ RTC_GUARDED_BY(mutex_); // Used for testing. - uint32_t sent_packets_ = 0; + uint32_t sent_packets_ RTC_GUARDED_BY(mutex_) = 0; std::map delay_by_ip_; std::map alternative_address_mapping_; std::unique_ptr delay_dist_; - double drop_prob_; + double drop_prob_ RTC_GUARDED_BY(mutex_); // The largest UDP payload permitted on this virtual socket server. // The default is the max size of IPv4 fragmented UDP packet payload: // 65535 bytes - 8 bytes UDP header - 20 bytes IP header. - size_t max_udp_payload_ = 65507; - // The largest UDP payload seen so far. - size_t largest_seen_udp_payload_ = 0; + size_t max_udp_payload_ RTC_GUARDED_BY(mutex_) = 65507; - bool sending_blocked_ = false; + bool sending_blocked_ RTC_GUARDED_BY(mutex_) = false; RTC_DISALLOW_COPY_AND_ASSIGN(VirtualSocketServer); };