| /* | |
| * Copyright 2004 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 P2P_TEST_NAT_SOCKET_FACTORY_H_ | |
| #define P2P_TEST_NAT_SOCKET_FACTORY_H_ | |
| #include <cstddef> | |
| #include <cstdint> | |
| #include <map> | |
| #include <memory> | |
| #include <set> | |
| #include <span> | |
| #include "api/environment/environment.h" | |
| #include "api/units/time_delta.h" | |
| #include "p2p/test/nat_server.h" | |
| #include "p2p/test/nat_types.h" | |
| #include "rtc_base/buffer.h" | |
| #include "rtc_base/socket.h" | |
| #include "rtc_base/socket_address.h" | |
| #include "rtc_base/socket_factory.h" | |
| #include "rtc_base/socket_server.h" | |
| #include "rtc_base/thread.h" | |
| namespace webrtc { | |
| const size_t kNATEncodedIPv4AddressSize = 8U; | |
| const size_t kNATEncodedIPv6AddressSize = 20U; | |
| // Used by the NAT socket implementation. | |
| class NATInternalSocketFactory { | |
| public: | |
| virtual ~NATInternalSocketFactory() {} | |
| virtual Socket* CreateInternalSocket(int family, | |
| int type, | |
| const SocketAddress& local_addr, | |
| SocketAddress* nat_addr) = 0; | |
| }; | |
| // Creates sockets that will send all traffic through a NAT, using an existing | |
| // NATServer instance running at nat_addr. The actual data is sent using sockets | |
| // from a socket factory, given to the constructor. | |
| class NATSocketFactory : public SocketFactory, public NATInternalSocketFactory { | |
| public: | |
| NATSocketFactory(SocketFactory* factory, | |
| const SocketAddress& nat_udp_addr, | |
| const SocketAddress& nat_tcp_addr); | |
| NATSocketFactory(const NATSocketFactory&) = delete; | |
| NATSocketFactory& operator=(const NATSocketFactory&) = delete; | |
| // SocketFactory implementation | |
| Socket* CreateSocket(int family, int type) override; | |
| // NATInternalSocketFactory implementation | |
| Socket* CreateInternalSocket(int family, | |
| int type, | |
| const SocketAddress& local_addr, | |
| SocketAddress* nat_addr) override; | |
| private: | |
| SocketFactory* factory_; | |
| SocketAddress nat_udp_addr_; | |
| SocketAddress nat_tcp_addr_; | |
| }; | |
| // Creates sockets that will send traffic through a NAT depending on what | |
| // address they bind to. This can be used to simulate a client on a NAT sending | |
| // to a client that is not behind a NAT. | |
| // Note that the internal addresses of clients must be unique. This is because | |
| // there is only one socketserver per thread, and the Bind() address is used to | |
| // figure out which NAT (if any) the socket should talk to. | |
| // | |
| // Example with 3 NATs (2 cascaded), and 3 clients. | |
| // ss->AddTranslator("1.2.3.4", "192.168.0.1", NAT_ADDR_RESTRICTED); | |
| // ss->AddTranslator("99.99.99.99", "10.0.0.1", NAT_SYMMETRIC)-> | |
| // AddTranslator("10.0.0.2", "192.168.1.1", NAT_OPEN_CONE); | |
| // ss->GetTranslator("1.2.3.4")->AddClient("1.2.3.4", "192.168.0.2"); | |
| // ss->GetTranslator("99.99.99.99")->AddClient("10.0.0.3"); | |
| // ss->GetTranslator("99.99.99.99")->GetTranslator("10.0.0.2")-> | |
| // AddClient("192.168.1.2"); | |
| class NATSocketServer : public SocketServer, public NATInternalSocketFactory { | |
| public: | |
| class Translator; | |
| // holds a list of NATs | |
| class TranslatorMap : private std::map<SocketAddress, Translator*> { | |
| public: | |
| ~TranslatorMap(); | |
| Translator* Get(const SocketAddress& ext_ip); | |
| Translator* Add(const SocketAddress& ext_ip, Translator*); | |
| void Remove(const SocketAddress& ext_ip); | |
| Translator* FindClient(const SocketAddress& int_ip); | |
| }; | |
| // a specific NAT | |
| class Translator { | |
| public: | |
| Translator(const Environment& env, | |
| NATSocketServer* server, | |
| NATType type, | |
| const SocketAddress& int_addr, | |
| Thread& external_socket_thread, | |
| SocketFactory* ext_factory, | |
| const SocketAddress& ext_addr); | |
| ~Translator(); | |
| SocketFactory* internal_factory() { return internal_server_.get(); } | |
| SocketAddress internal_udp_address() const { | |
| return nat_server_->internal_udp_address(); | |
| } | |
| SocketAddress internal_tcp_address() const { | |
| return SocketAddress(); // nat_server_->internal_tcp_address(); | |
| } | |
| Translator* GetTranslator(const SocketAddress& ext_ip); | |
| Translator* AddTranslator(const Environment& env, | |
| const SocketAddress& ext_ip, | |
| const SocketAddress& int_ip, | |
| NATType type); | |
| void RemoveTranslator(const SocketAddress& ext_ip); | |
| bool AddClient(const SocketAddress& int_ip); | |
| void RemoveClient(const SocketAddress& int_ip); | |
| // Looks for the specified client in this or a child NAT. | |
| Translator* FindClient(const SocketAddress& int_ip); | |
| private: | |
| NATSocketServer* server_; | |
| std::unique_ptr<SocketServer> internal_server_; | |
| std::unique_ptr<NATServer> nat_server_; | |
| TranslatorMap nats_; | |
| std::set<SocketAddress> clients_; | |
| }; | |
| explicit NATSocketServer(SocketServer* ss); | |
| NATSocketServer(const NATSocketServer&) = delete; | |
| NATSocketServer& operator=(const NATSocketServer&) = delete; | |
| SocketServer* socketserver() { return server_; } | |
| Thread* queue() { return msg_queue_; } | |
| Translator* GetTranslator(const SocketAddress& ext_ip); | |
| Translator* AddTranslator(const Environment& env, | |
| const SocketAddress& ext_ip, | |
| const SocketAddress& int_ip, | |
| NATType type); | |
| void RemoveTranslator(const SocketAddress& ext_ip); | |
| // SocketServer implementation | |
| Socket* CreateSocket(int family, int type) override; | |
| void SetMessageQueue(Thread* queue) override; | |
| bool Wait(TimeDelta max_wait_duration, bool process_io) override; | |
| void WakeUp() override; | |
| // NATInternalSocketFactory implementation | |
| Socket* CreateInternalSocket(int family, | |
| int type, | |
| const SocketAddress& local_addr, | |
| SocketAddress* nat_addr) override; | |
| private: | |
| SocketServer* server_; | |
| Thread* msg_queue_; | |
| TranslatorMap nats_; | |
| }; | |
| // Free-standing NAT helper functions. | |
| void PackAddressForNAT(const SocketAddress& remote_addr, Buffer& buf); | |
| size_t UnpackAddressFromNAT(std::span<const uint8_t> buf, | |
| SocketAddress* remote_addr); | |
| } // namespace webrtc | |
| #endif // P2P_TEST_NAT_SOCKET_FACTORY_H_ |