Coverage Report

Created: 2025-09-17 06:57

next uncovered line (L), next uncovered region (R), next uncovered branch (B)
/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