/* * 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 RTC_BASE_FIREWALL_SOCKET_SERVER_H_ #define RTC_BASE_FIREWALL_SOCKET_SERVER_H_ #include #include "rtc_base/async_socket.h" #include "rtc_base/ip_address.h" #include "rtc_base/socket.h" #include "rtc_base/socket_address.h" #include "rtc_base/socket_server.h" #include "rtc_base/synchronization/mutex.h" namespace rtc { class FirewallManager; // This SocketServer shim simulates a rule-based firewall server. enum FirewallProtocol { FP_UDP, FP_TCP, FP_ANY }; enum FirewallDirection { FD_IN, FD_OUT, FD_ANY }; class FirewallSocketServer : public SocketServer { public: FirewallSocketServer(SocketServer* server, FirewallManager* manager = nullptr, bool should_delete_server = false); ~FirewallSocketServer() override; SocketServer* socketserver() const { return server_; } void set_socketserver(SocketServer* server) { if (server_ && should_delete_server_) { delete server_; server_ = nullptr; should_delete_server_ = false; } server_ = server; } // Settings to control whether CreateSocket or Socket::Listen succeed. void set_udp_sockets_enabled(bool enabled) { udp_sockets_enabled_ = enabled; } void set_tcp_sockets_enabled(bool enabled) { tcp_sockets_enabled_ = enabled; } bool tcp_listen_enabled() const { return tcp_listen_enabled_; } void set_tcp_listen_enabled(bool enabled) { tcp_listen_enabled_ = enabled; } // Rules govern the behavior of Connect/Accept/Send/Recv attempts. void AddRule(bool allow, FirewallProtocol p = FP_ANY, FirewallDirection d = FD_ANY, const SocketAddress& addr = SocketAddress()); void AddRule(bool allow, FirewallProtocol p, const SocketAddress& src, const SocketAddress& dst); void ClearRules(); bool Check(FirewallProtocol p, const SocketAddress& src, const SocketAddress& dst); // Set the IP addresses for which Bind will fail. By default this list is // empty. This can be used to simulate a real OS that refuses to bind to // addresses under various circumstances. // // No matter how many addresses are added (including INADDR_ANY), the server // will still allow creating outgoing TCP connections, since they don't // require explicitly binding a socket. void SetUnbindableIps(const std::vector& unbindable_ips); bool IsBindableIp(const rtc::IPAddress& ip); Socket* CreateSocket(int family, int type) override; AsyncSocket* CreateAsyncSocket(int family, int type) override; void SetMessageQueue(Thread* queue) override; bool Wait(int cms, bool process_io) override; void WakeUp() override; Socket* WrapSocket(Socket* sock, int type); AsyncSocket* WrapSocket(AsyncSocket* sock, int type); private: SocketServer* server_; FirewallManager* manager_; webrtc::Mutex mutex_; struct Rule { bool allow; FirewallProtocol p; FirewallDirection d; SocketAddress src; SocketAddress dst; }; std::vector rules_; std::vector unbindable_ips_; bool should_delete_server_; bool udp_sockets_enabled_; bool tcp_sockets_enabled_; bool tcp_listen_enabled_; }; // FirewallManager allows you to manage firewalls in multiple threads together class FirewallManager { public: FirewallManager(); ~FirewallManager(); void AddServer(FirewallSocketServer* server); void RemoveServer(FirewallSocketServer* server); void AddRule(bool allow, FirewallProtocol p = FP_ANY, FirewallDirection d = FD_ANY, const SocketAddress& addr = SocketAddress()); void ClearRules(); private: webrtc::Mutex mutex_; std::vector servers_; }; } // namespace rtc #endif // RTC_BASE_FIREWALL_SOCKET_SERVER_H_