1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
// Copyright (c) 2011 Baidu.com, Inc. All Rights Reserved
//
// Wrappers of IP and port.
//
// Author: Ge,Jun (gejun@baidu.com)
// Date: Mon. Nov 7 14:47:36 CST 2011
#ifndef BRPC_BASE_ENDPOINT_H
#define BRPC_BASE_ENDPOINT_H
#include <netinet/in.h> // in_addr
#include <iostream> // std::ostream
#include "base/containers/hash_tables.h" // hashing functions
namespace base {
// Type of an IP address
typedef struct in_addr ip_t;
static const ip_t IP_ANY = { INADDR_ANY };
static const ip_t IP_NONE = { INADDR_NONE };
// Convert |ip| to an integral
inline in_addr_t ip2int(ip_t ip) { return ip.s_addr; }
// Convert integral |ip_value| to an IP
inline ip_t int2ip(in_addr_t ip_value) {
const ip_t ip = { ip_value };
return ip;
}
// Convert string `ip_str' to ip_t *ip.
// `ip_str' is in IPv4 dotted-quad format: `127.0.0.1', `10.23.249.73' ...
// Returns 0 on success, -1 otherwise.
int str2ip(const char* ip_str, ip_t* ip);
struct IPStr {
const char* c_str() const { return _buf; }
char _buf[INET_ADDRSTRLEN];
};
// Convert IP to c-style string. Notice that you can serialize ip_t to
// std::ostream directly. Use this function when you don't have streaming log.
// Example: printf("ip=%s\n", ip2str(some_ip).c_str());
IPStr ip2str(ip_t ip);
// Convert `hostname' to ip_t *ip. If `hostname' is NULL, use hostname
// of this machine.
// `hostname' is typically in this form: `tc-cm-et21.tc' `db-cos-dev.db01' ...
// Returns 0 on success, -1 otherwise.
int hostname2ip(const char* hostname, ip_t* ip);
// Convert `ip' to `hostname'.
// Returns 0 on success, -1 otherwise and errno is set.
int ip2hostname(ip_t ip, char* hostname, size_t hostname_len);
int ip2hostname(ip_t ip, std::string* hostname);
// Hostname of this machine, "" on error.
// NOTE: This function caches result on first call.
const char* my_hostname();
// IP of this machine, IP_ANY on error.
// NOTE: This function caches result on first call.
ip_t my_ip();
// String form.
const char* my_ip_cstr();
// ipv4 + port
struct EndPoint {
EndPoint() : ip(IP_ANY), port(0) {}
EndPoint(ip_t ip2, int port2) : ip(ip2), port(port2) {}
explicit EndPoint(const sockaddr_in& in)
: ip(in.sin_addr), port(ntohs(in.sin_port)) {}
ip_t ip;
int port;
};
struct EndPointStr {
const char* c_str() const { return _buf; }
char _buf[INET_ADDRSTRLEN + 16];
};
// Convert EndPoint to c-style string. Notice that you can serialize
// EndPoint to std::ostream directly. Use this function when you don't
// have streaming log.
// Example: printf("point=%s\n", endpoint2str(point).c_str());
EndPointStr endpoint2str(const EndPoint&);
// Convert string `ip_and_port_str' to a EndPoint *point.
// Returns 0 on success, -1 otherwise.
int str2endpoint(const char* ip_and_port_str, EndPoint* point);
int str2endpoint(const char* ip_str, int port, EndPoint* point);
// Convert `hostname_and_port_str' to a EndPoint *point.
// Returns 0 on success, -1 otherwise.
int hostname2endpoint(const char* ip_and_port_str, EndPoint* point);
int hostname2endpoint(const char* name_str, int port, EndPoint* point);
// Convert `endpoint' to `hostname'.
// Returns 0 on success, -1 otherwise and errno is set.
int endpoint2hostname(const EndPoint& point, char* hostname, size_t hostname_len);
int endpoint2hostname(const EndPoint& point, std::string* host);
// Create a TCP socket and connect it to `server'. Write port of this side
// into `self_port' if it's not NULL.
// Returns the socket descriptor, -1 otherwise and errno is set.
int tcp_connect(EndPoint server, int* self_port);
// Create and listen to a TCP socket bound with `ip_and_port'. If `reuse_addr'
// is true, ports in TIME_WAIT will be bound as well.
// Returns the socket descriptor, -1 otherwise and errno is set.
int tcp_listen(EndPoint ip_and_port, bool reuse_addr);
// Get the local end of a socket connection
int get_local_side(int fd, EndPoint *out);
// Get the other end of a socket connection
int get_remote_side(int fd, EndPoint *out);
} // namespace base
// Since ip_t is defined from in_addr which is globally defined, due to ADL
// we have to put overloaded operators globally as well.
inline bool operator<(base::ip_t lhs, base::ip_t rhs) {
return base::ip2int(lhs) < base::ip2int(rhs);
}
inline bool operator>(base::ip_t lhs, base::ip_t rhs) {
return rhs < lhs;
}
inline bool operator>=(base::ip_t lhs, base::ip_t rhs) {
return !(lhs < rhs);
}
inline bool operator<=(base::ip_t lhs, base::ip_t rhs) {
return !(rhs < lhs);
}
inline bool operator==(base::ip_t lhs, base::ip_t rhs) {
return base::ip2int(lhs) == base::ip2int(rhs);
}
inline bool operator!=(base::ip_t lhs, base::ip_t rhs) {
return !(lhs == rhs);
}
inline std::ostream& operator<<(std::ostream& os, const base::IPStr& ip_str) {
return os << ip_str.c_str();
}
inline std::ostream& operator<<(std::ostream& os, base::ip_t ip) {
return os << base::ip2str(ip);
}
namespace base {
// Overload operators for EndPoint in the same namespace due to ADL.
inline bool operator<(EndPoint p1, EndPoint p2) {
return (p1.ip != p2.ip) ? (p1.ip < p2.ip) : (p1.port < p2.port);
}
inline bool operator>(EndPoint p1, EndPoint p2) {
return p2 < p1;
}
inline bool operator<=(EndPoint p1, EndPoint p2) {
return !(p2 < p1);
}
inline bool operator>=(EndPoint p1, EndPoint p2) {
return !(p1 < p2);
}
inline bool operator==(EndPoint p1, EndPoint p2) {
return p1.ip == p2.ip && p1.port == p2.port;
}
inline bool operator!=(EndPoint p1, EndPoint p2) {
return !(p1 == p2);
}
inline std::ostream& operator<<(std::ostream& os, const EndPoint& ep) {
return os << ep.ip << ':' << ep.port;
}
inline std::ostream& operator<<(std::ostream& os, const EndPointStr& ep_str) {
return os << ep_str.c_str();
}
} // namespace base
namespace BASE_HASH_NAMESPACE {
// Implement methods for hashing a pair of integers, so they can be used as
// keys in STL containers.
#if defined(COMPILER_MSVC)
inline std::size_t hash_value(const base::EndPoint& ep) {
return base::HashPair(base::ip2int(ep.ip), ep.port);
}
#elif defined(COMPILER_GCC)
template <>
struct hash<base::EndPoint> {
std::size_t operator()(const base::EndPoint& ep) const {
return base::HashPair(base::ip2int(ep.ip), ep.port);
}
};
#else
#error define hash<EndPoint> for your compiler
#endif // COMPILER
}
#endif // BRPC_BASE_ENDPOINT_H