/src/brpc/src/butil/endpoint.h
Line | Count | Source |
1 | | // Licensed to the Apache Software Foundation (ASF) under one |
2 | | // or more contributor license agreements. See the NOTICE file |
3 | | // distributed with this work for additional information |
4 | | // regarding copyright ownership. The ASF licenses this file |
5 | | // to you under the Apache License, Version 2.0 (the |
6 | | // "License"); you may not use this file except in compliance |
7 | | // with the License. You may obtain a copy of the License at |
8 | | // |
9 | | // http://www.apache.org/licenses/LICENSE-2.0 |
10 | | // |
11 | | // Unless required by applicable law or agreed to in writing, |
12 | | // software distributed under the License is distributed on an |
13 | | // "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
14 | | // KIND, either express or implied. See the License for the |
15 | | // specific language governing permissions and limitations |
16 | | // under the License. |
17 | | |
18 | | // Date: Mon. Nov 7 14:47:36 CST 2011 |
19 | | |
20 | | // Wrappers of IP and port. |
21 | | |
22 | | #ifndef BUTIL_ENDPOINT_H |
23 | | #define BUTIL_ENDPOINT_H |
24 | | |
25 | | #include <netinet/in.h> // in_addr |
26 | | #include <sys/un.h> // sockaddr_un |
27 | | #include <iostream> // std::ostream |
28 | | #include "butil/containers/hash_tables.h" // hashing functions |
29 | | |
30 | | namespace butil { |
31 | | |
32 | | // Type of an IP address |
33 | | typedef struct in_addr ip_t; |
34 | | |
35 | | static const ip_t IP_ANY = { INADDR_ANY }; |
36 | | static const ip_t IP_NONE = { INADDR_NONE }; |
37 | | static const int MAX_DOMAIN_LENGTH = 253; |
38 | | |
39 | | // Convert |ip| to an integral |
40 | 0 | inline in_addr_t ip2int(ip_t ip) { return ip.s_addr; } |
41 | | |
42 | | // Convert integral |ip_value| to an IP |
43 | 0 | inline ip_t int2ip(in_addr_t ip_value) { |
44 | 0 | const ip_t ip = { ip_value }; |
45 | 0 | return ip; |
46 | 0 | } |
47 | | |
48 | | // Convert string `ip_str' to ip_t *ip. |
49 | | // `ip_str' is in IPv4 dotted-quad format: `127.0.0.1', `10.23.249.73' ... |
50 | | // Returns 0 on success, -1 otherwise. |
51 | | int str2ip(const char* ip_str, ip_t* ip); |
52 | | |
53 | | struct IPStr { |
54 | 0 | const char* c_str() const { return _buf; } |
55 | | char _buf[INET_ADDRSTRLEN]; |
56 | | }; |
57 | | |
58 | | // Convert IP to c-style string. Notice that you can serialize ip_t to |
59 | | // std::ostream directly. Use this function when you don't have streaming log. |
60 | | // Example: printf("ip=%s\n", ip2str(some_ip).c_str()); |
61 | | IPStr ip2str(ip_t ip); |
62 | | |
63 | | // Convert `hostname' to ip_t *ip. If `hostname' is NULL, use hostname |
64 | | // of this machine. |
65 | | // `hostname' is typically in this form: `tc-cm-et21.tc' `db-cos-dev.db01' ... |
66 | | // Returns 0 on success, -1 otherwise. |
67 | | int hostname2ip(const char* hostname, ip_t* ip); |
68 | | |
69 | | // Convert `ip' to `hostname'. |
70 | | // Returns 0 on success, -1 otherwise and errno is set. |
71 | | int ip2hostname(ip_t ip, char* hostname, size_t hostname_len); |
72 | | int ip2hostname(ip_t ip, std::string* hostname); |
73 | | |
74 | | // Hostname of this machine, "" on error. |
75 | | // NOTE: This function caches result on first call. |
76 | | const char* my_hostname(); |
77 | | |
78 | | // IP of this machine, IP_ANY on error. |
79 | | // NOTE: This function caches result on first call. |
80 | | ip_t my_ip(); |
81 | | // String form. |
82 | | const char* my_ip_cstr(); |
83 | | |
84 | | // For IPv4 endpoint, ip and port are real things. |
85 | | // For UDS/IPv6 endpoint, to keep ABI compatibility, ip is ResourceId, and port is a special flag. |
86 | | // See str2endpoint implementation for details. |
87 | | struct EndPoint { |
88 | 0 | EndPoint() : ip(IP_ANY), port(0) {} |
89 | | EndPoint(ip_t ip2, int port2); |
90 | | explicit EndPoint(const sockaddr_in& in) |
91 | 0 | : ip(in.sin_addr), port(ntohs(in.sin_port)) {} |
92 | | |
93 | | EndPoint(const EndPoint&); |
94 | | ~EndPoint(); |
95 | | void operator=(const EndPoint&); |
96 | | |
97 | | void reset(void); |
98 | | |
99 | | ip_t ip; |
100 | | int port; |
101 | | }; |
102 | | |
103 | | struct EndPointStr { |
104 | 0 | const char* c_str() const { return _buf; } |
105 | | char _buf[sizeof("unix:") + sizeof(sockaddr_un::sun_path)]; |
106 | | }; |
107 | | |
108 | | // Convert EndPoint to c-style string. Notice that you can serialize |
109 | | // EndPoint to std::ostream directly. Use this function when you don't |
110 | | // have streaming log. |
111 | | // Example: printf("point=%s\n", endpoint2str(point).c_str()); |
112 | | EndPointStr endpoint2str(const EndPoint&); |
113 | | |
114 | | // Convert string `ip_and_port_str' to a EndPoint *point. |
115 | | // Returns 0 on success, -1 otherwise. |
116 | | int str2endpoint(const char* ip_and_port_str, EndPoint* point); |
117 | | int str2endpoint(const char* ip_str, int port, EndPoint* point); |
118 | | |
119 | | // Convert `hostname_and_port_str' to a EndPoint *point. |
120 | | // Returns 0 on success, -1 otherwise. |
121 | | int hostname2endpoint(const char* ip_and_port_str, EndPoint* point); |
122 | | int hostname2endpoint(const char* name_str, int port, EndPoint* point); |
123 | | |
124 | | // Convert `endpoint' to `hostname'. |
125 | | // Returns 0 on success, -1 otherwise and errno is set. |
126 | | int endpoint2hostname(const EndPoint& point, char* hostname, size_t hostname_len); |
127 | | int endpoint2hostname(const EndPoint& point, std::string* host); |
128 | | |
129 | | // Create a TCP socket and connect it to `server'. Write port of this side |
130 | | // into `self_port' if it's not NULL. |
131 | | // Returns the socket descriptor, -1 otherwise and errno is set. |
132 | | int tcp_connect(EndPoint server, int* self_port); |
133 | | // Suspend caller thread until connect(2) on `sockfd' succeeds |
134 | | // or CLOCK_REALTIME reached `abstime' if `abstime' is not NULL. |
135 | | // Write port of this side into `self_port' if it's not NULL. |
136 | | // Returns the socket descriptor, -1 otherwise and errno is set. |
137 | | int tcp_connect(const EndPoint& server, int* self_port, int connect_timeout_ms); |
138 | | |
139 | | // Create and listen to a TCP socket bound with `ip_and_port'. |
140 | | // To enable SO_REUSEADDR for the whole program, enable gflag -reuse_addr |
141 | | // To enable SO_REUSEPORT for the whole program, enable gflag -reuse_port |
142 | | // Returns the socket descriptor, -1 otherwise and errno is set. |
143 | | int tcp_listen(EndPoint ip_and_port); |
144 | | |
145 | | // Get the local end of a socket connection |
146 | | int get_local_side(int fd, EndPoint *out); |
147 | | |
148 | | // Get the other end of a socket connection |
149 | | int get_remote_side(int fd, EndPoint *out); |
150 | | |
151 | | // Get sockaddr from endpoint, return -1 on failed |
152 | | int endpoint2sockaddr(const EndPoint& point, struct sockaddr_storage* ss, socklen_t* size = NULL); |
153 | | |
154 | | // Create endpoint from sockaddr, return -1 on failed |
155 | | int sockaddr2endpoint(struct sockaddr_storage* ss, socklen_t size, EndPoint* point); |
156 | | |
157 | | // Get EndPoint type (AF_INET/AF_INET6/AF_UNIX) |
158 | | sa_family_t get_endpoint_type(const EndPoint& point); |
159 | | |
160 | | // Check if endpoint is extended. |
161 | | bool is_endpoint_extended(const EndPoint& point); |
162 | | |
163 | | } // namespace butil |
164 | | |
165 | | // Since ip_t is defined from in_addr which is globally defined, due to ADL |
166 | | // we have to put overloaded operators globally as well. |
167 | 0 | inline bool operator<(butil::ip_t lhs, butil::ip_t rhs) { |
168 | 0 | return butil::ip2int(lhs) < butil::ip2int(rhs); |
169 | 0 | } |
170 | 0 | inline bool operator>(butil::ip_t lhs, butil::ip_t rhs) { |
171 | 0 | return rhs < lhs; |
172 | 0 | } |
173 | 0 | inline bool operator>=(butil::ip_t lhs, butil::ip_t rhs) { |
174 | 0 | return !(lhs < rhs); |
175 | 0 | } |
176 | 0 | inline bool operator<=(butil::ip_t lhs, butil::ip_t rhs) { |
177 | 0 | return !(rhs < lhs); |
178 | 0 | } |
179 | 0 | inline bool operator==(butil::ip_t lhs, butil::ip_t rhs) { |
180 | 0 | return butil::ip2int(lhs) == butil::ip2int(rhs); |
181 | 0 | } |
182 | 0 | inline bool operator!=(butil::ip_t lhs, butil::ip_t rhs) { |
183 | 0 | return !(lhs == rhs); |
184 | 0 | } |
185 | | |
186 | 0 | inline std::ostream& operator<<(std::ostream& os, const butil::IPStr& ip_str) { |
187 | 0 | return os << ip_str.c_str(); |
188 | 0 | } |
189 | 0 | inline std::ostream& operator<<(std::ostream& os, butil::ip_t ip) { |
190 | 0 | return os << butil::ip2str(ip); |
191 | 0 | } |
192 | | |
193 | | namespace butil { |
194 | | // Overload operators for EndPoint in the same namespace due to ADL. |
195 | 0 | inline bool operator<(EndPoint p1, EndPoint p2) { |
196 | 0 | return (p1.ip != p2.ip) ? (p1.ip < p2.ip) : (p1.port < p2.port); |
197 | 0 | } |
198 | 0 | inline bool operator>(EndPoint p1, EndPoint p2) { |
199 | 0 | return p2 < p1; |
200 | 0 | } |
201 | 0 | inline bool operator<=(EndPoint p1, EndPoint p2) { |
202 | 0 | return !(p2 < p1); |
203 | 0 | } |
204 | 0 | inline bool operator>=(EndPoint p1, EndPoint p2) { |
205 | 0 | return !(p1 < p2); |
206 | 0 | } |
207 | 0 | inline bool operator==(EndPoint p1, EndPoint p2) { |
208 | 0 | return p1.ip == p2.ip && p1.port == p2.port; |
209 | 0 | } |
210 | 0 | inline bool operator!=(EndPoint p1, EndPoint p2) { |
211 | 0 | return !(p1 == p2); |
212 | 0 | } |
213 | | |
214 | 0 | inline std::ostream& operator<<(std::ostream& os, const EndPoint& ep) { |
215 | 0 | return os << endpoint2str(ep).c_str(); |
216 | 0 | } |
217 | 0 | inline std::ostream& operator<<(std::ostream& os, const EndPointStr& ep_str) { |
218 | 0 | return os << ep_str.c_str(); |
219 | 0 | } |
220 | | |
221 | | } // namespace butil |
222 | | |
223 | | |
224 | | namespace BUTIL_HASH_NAMESPACE { |
225 | | |
226 | | // Implement methods for hashing a pair of integers, so they can be used as |
227 | | // keys in STL containers. |
228 | | |
229 | | #if defined(COMPILER_MSVC) |
230 | | |
231 | | inline std::size_t hash_value(const butil::EndPoint& ep) { |
232 | | return butil::HashPair(butil::ip2int(ep.ip), ep.port); |
233 | | } |
234 | | |
235 | | #elif defined(COMPILER_GCC) |
236 | | template <> |
237 | | struct hash<butil::EndPoint> { |
238 | 0 | std::size_t operator()(const butil::EndPoint& ep) const { |
239 | 0 | return butil::HashPair(butil::ip2int(ep.ip), ep.port); |
240 | 0 | } |
241 | | }; |
242 | | |
243 | | #else |
244 | | #error define hash<EndPoint> for your compiler |
245 | | #endif // COMPILER |
246 | | |
247 | | } |
248 | | |
249 | | #endif // BUTIL_ENDPOINT_H |