1 //
2 // Copyright Aliaksei Levin (levlam@telegram.org), Arseny Smirnov (arseny30@gmail.com) 2014-2021
3 //
4 // Distributed under the Boost Software License, Version 1.0. (See accompanying
5 // file LICENSE_1_0.txt or copy at http://www.boost.org/LICENSE_1_0.txt)
6 //
7 #pragma once
8 
9 #include "td/utils/port/config.h"
10 
11 #include "td/utils/common.h"
12 #include "td/utils/Slice.h"
13 #include "td/utils/Status.h"
14 #include "td/utils/StringBuilder.h"
15 
16 #if !TD_WINDOWS
17 #include <arpa/inet.h>
18 #include <netinet/in.h>
19 #include <sys/socket.h>
20 #endif
21 
22 namespace td {
23 
24 Result<string> idn_to_ascii(CSlice host);
25 
26 class SocketFd;
27 
28 class IPAddress {
29  public:
30   IPAddress();
31 
32   bool is_valid() const;
33   bool is_ipv4() const;
34   bool is_ipv6() const;
35 
36   bool is_reserved() const;
37 
38   int get_port() const;
39   void set_port(int port);
40 
41   uint32 get_ipv4() const;
42   string get_ipv6() const;
43 
44   // returns result in a static thread-local buffer, which may be overwritten by any subsequent method call
45   CSlice get_ip_str() const;
46 
47   // returns IP address as a host, i.e. IPv4 or [IPv6]
48   string get_ip_host() const;
49 
50   static string ipv4_to_str(uint32 ipv4);
51   static string ipv6_to_str(Slice ipv6);
52 
53   IPAddress get_any_addr() const;
54 
55   static Result<IPAddress> get_ip_address(CSlice host);  // host must be any IPv4 or IPv6
56   static Result<IPAddress> get_ipv4_address(CSlice host);
57   static Result<IPAddress> get_ipv6_address(CSlice host);
58 
59   Status init_ipv6_port(CSlice ipv6, int port) TD_WARN_UNUSED_RESULT;
60   Status init_ipv6_as_ipv4_port(CSlice ipv4, int port) TD_WARN_UNUSED_RESULT;
61   Status init_ipv4_port(CSlice ipv4, int port) TD_WARN_UNUSED_RESULT;
62   Status init_host_port(CSlice host, int port, bool prefer_ipv6 = false) TD_WARN_UNUSED_RESULT;
63   Status init_host_port(CSlice host, CSlice port, bool prefer_ipv6 = false) TD_WARN_UNUSED_RESULT;
64   Status init_host_port(CSlice host_port) TD_WARN_UNUSED_RESULT;
65   Status init_socket_address(const SocketFd &socket_fd) TD_WARN_UNUSED_RESULT;
66   Status init_peer_address(const SocketFd &socket_fd) TD_WARN_UNUSED_RESULT;
67 
68   void clear_ipv6_interface();
69 
70   friend bool operator==(const IPAddress &a, const IPAddress &b);
71   friend bool operator<(const IPAddress &a, const IPAddress &b);
72 
73   // for internal usage only
74   const sockaddr *get_sockaddr() const;
75   size_t get_sockaddr_len() const;
76   int get_address_family() const;
77   Status init_sockaddr(sockaddr *addr);
78   Status init_sockaddr(sockaddr *addr, socklen_t len) TD_WARN_UNUSED_RESULT;
79 
80  private:
81   union {
82     sockaddr sockaddr_;
83     sockaddr_in ipv4_addr_;
84     sockaddr_in6 ipv6_addr_;
85   };
storage_size()86   static constexpr socklen_t storage_size() {
87     return sizeof(ipv6_addr_);
88   }
89   bool is_valid_;
90 
91   void init_ipv4_any();
92   void init_ipv6_any();
93 };
94 
95 StringBuilder &operator<<(StringBuilder &builder, const IPAddress &address);
96 
97 }  // namespace td
98