/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  |