mirror of
https://github.com/mollyim/webrtc.git
synced 2025-05-13 13:50:40 +01:00

Original patch contributed by andrey.semashev@gmail.com. In PhysicalSocketServer::WaitEpoll(), the loop verifies that the signalled dispatcher is in dispatchers_ set. It does so by looking up the dispatcher pointer in the set. This is vulnerable to the ABA problem because one dispatcher may be removed and destroyed and another created and added with the same address before epoll reports an event for the old dispatcher. The same issue exists for other Wait implementations, if a dispatcher is removed and a new one added with the same socket handle is the old. This is avoided by using a 64-bit key for looking up the dispatcher in the set. The key is set from a running counter which gets incremented when a dispatcher is added to the set, so even if the same dispatcher pointer is added, removed and added again, the key value will be different. This changes the storage of dispatchers_ from a set to a flat_hash_map, which uses a bit more memory but has faster lookup (O(1) as opposed to O(log n)). Bug: webrtc:11124 Change-Id: I6d206e1a367b58ba971edca9b48af7664384b797 Reviewed-on: https://webrtc-review.googlesource.com/c/src/+/181027 Commit-Queue: Taylor <deadbeef@webrtc.org> Reviewed-by: Karl Wiberg <kwiberg@webrtc.org> Cr-Commit-Position: refs/heads/master@{#32019}
105 lines
3.8 KiB
C++
105 lines
3.8 KiB
C++
/*
|
|
* Copyright 2009 The WebRTC Project Authors. All rights reserved.
|
|
*
|
|
* Use of this source code is governed by a BSD-style license
|
|
* that can be found in the LICENSE file in the root of the source
|
|
* tree. An additional intellectual property rights grant can be found
|
|
* in the file PATENTS. All contributing project authors may
|
|
* be found in the AUTHORS file in the root of the source tree.
|
|
*/
|
|
|
|
#ifndef RTC_BASE_SOCKET_UNITTEST_H_
|
|
#define RTC_BASE_SOCKET_UNITTEST_H_
|
|
|
|
#include "rtc_base/gunit.h"
|
|
#include "rtc_base/thread.h"
|
|
|
|
namespace rtc {
|
|
|
|
// Generic socket tests, to be used when testing individual socketservers.
|
|
// Derive your specific test class from SocketTest, install your
|
|
// socketserver, and call the SocketTest test methods.
|
|
class SocketTest : public ::testing::Test {
|
|
protected:
|
|
SocketTest()
|
|
: kIPv4Loopback(INADDR_LOOPBACK),
|
|
kIPv6Loopback(in6addr_loopback),
|
|
ss_(nullptr) {}
|
|
void SetUp() override;
|
|
void TestConnectIPv4();
|
|
void TestConnectIPv6();
|
|
void TestConnectWithDnsLookupIPv4();
|
|
void TestConnectWithDnsLookupIPv6();
|
|
void TestConnectFailIPv4();
|
|
void TestConnectFailIPv6();
|
|
void TestConnectWithDnsLookupFailIPv4();
|
|
void TestConnectWithDnsLookupFailIPv6();
|
|
void TestConnectWithClosedSocketIPv4();
|
|
void TestConnectWithClosedSocketIPv6();
|
|
void TestConnectWhileNotClosedIPv4();
|
|
void TestConnectWhileNotClosedIPv6();
|
|
void TestServerCloseDuringConnectIPv4();
|
|
void TestServerCloseDuringConnectIPv6();
|
|
void TestClientCloseDuringConnectIPv4();
|
|
void TestClientCloseDuringConnectIPv6();
|
|
void TestServerCloseIPv4();
|
|
void TestServerCloseIPv6();
|
|
void TestCloseInClosedCallbackIPv4();
|
|
void TestCloseInClosedCallbackIPv6();
|
|
void TestDeleteInReadCallbackIPv4();
|
|
void TestDeleteInReadCallbackIPv6();
|
|
void TestSocketServerWaitIPv4();
|
|
void TestSocketServerWaitIPv6();
|
|
void TestTcpIPv4();
|
|
void TestTcpIPv6();
|
|
void TestSingleFlowControlCallbackIPv4();
|
|
void TestSingleFlowControlCallbackIPv6();
|
|
void TestUdpIPv4();
|
|
void TestUdpIPv6();
|
|
void TestUdpReadyToSendIPv4();
|
|
void TestUdpReadyToSendIPv6();
|
|
void TestGetSetOptionsIPv4();
|
|
void TestGetSetOptionsIPv6();
|
|
void TestSocketRecvTimestampIPv4();
|
|
void TestSocketRecvTimestampIPv6();
|
|
|
|
static const int kTimeout = 5000; // ms
|
|
const IPAddress kIPv4Loopback;
|
|
const IPAddress kIPv6Loopback;
|
|
|
|
protected:
|
|
void TcpInternal(const IPAddress& loopback,
|
|
size_t data_size,
|
|
ptrdiff_t max_send_size);
|
|
|
|
private:
|
|
void ConnectInternal(const IPAddress& loopback);
|
|
void ConnectWithDnsLookupInternal(const IPAddress& loopback,
|
|
const std::string& host);
|
|
void ConnectFailInternal(const IPAddress& loopback);
|
|
|
|
void ConnectWithDnsLookupFailInternal(const IPAddress& loopback);
|
|
void ConnectWithClosedSocketInternal(const IPAddress& loopback);
|
|
void ConnectWhileNotClosedInternal(const IPAddress& loopback);
|
|
void ServerCloseDuringConnectInternal(const IPAddress& loopback);
|
|
void ClientCloseDuringConnectInternal(const IPAddress& loopback);
|
|
void ServerCloseInternal(const IPAddress& loopback);
|
|
void CloseInClosedCallbackInternal(const IPAddress& loopback);
|
|
void DeleteInReadCallbackInternal(const IPAddress& loopback);
|
|
void SocketServerWaitInternal(const IPAddress& loopback);
|
|
void SingleFlowControlCallbackInternal(const IPAddress& loopback);
|
|
void UdpInternal(const IPAddress& loopback);
|
|
void UdpReadyToSend(const IPAddress& loopback);
|
|
void GetSetOptionsInternal(const IPAddress& loopback);
|
|
void SocketRecvTimestamp(const IPAddress& loopback);
|
|
|
|
SocketServer* ss_;
|
|
};
|
|
|
|
// For unbound sockets, GetLocalAddress / GetRemoteAddress return AF_UNSPEC
|
|
// values on Windows, but an empty address of the same family on Linux/MacOS X.
|
|
bool IsUnspecOrEmptyIP(const IPAddress& address);
|
|
|
|
} // namespace rtc
|
|
|
|
#endif // RTC_BASE_SOCKET_UNITTEST_H_
|