]>
Commit | Line | Data |
---|---|---|
11fdf7f2 | 1 | // -*- mode:C++; tab-width:8; c-basic-offset:2; indent-tabs-mode:t -*- |
7c673cae FG |
2 | // vim: ts=8 sw=2 smarttab |
3 | /* | |
4 | * Ceph - scalable distributed file system | |
5 | * | |
6 | * Copyright (C) 2004-2006 Sage Weil <sage@newdream.net> | |
7 | * | |
8 | * This is free software; you can redistribute it and/or | |
9 | * modify it under the terms of the GNU Lesser General Public | |
11fdf7f2 | 10 | * License version 2.1, as published by the Free Software |
7c673cae | 11 | * Foundation. See file COPYING. |
11fdf7f2 | 12 | * |
7c673cae FG |
13 | */ |
14 | ||
15 | #ifndef CEPH_MSG_TYPES_H | |
16 | #define CEPH_MSG_TYPES_H | |
17 | ||
11fdf7f2 TL |
18 | #include <sstream> |
19 | ||
7c673cae FG |
20 | #include <netinet/in.h> |
21 | ||
22 | #include "include/ceph_features.h" | |
23 | #include "include/types.h" | |
24 | #include "include/blobhash.h" | |
25 | #include "include/encoding.h" | |
26 | ||
11fdf7f2 TL |
27 | #define MAX_PORT_NUMBER 65535 |
28 | ||
7c673cae FG |
29 | namespace ceph { |
30 | class Formatter; | |
31 | } | |
32 | ||
9f95a23c TL |
33 | std::ostream& operator<<(std::ostream& out, const sockaddr_storage &ss); |
34 | std::ostream& operator<<(std::ostream& out, const sockaddr *sa); | |
7c673cae FG |
35 | |
36 | typedef uint8_t entity_type_t; | |
37 | ||
38 | class entity_name_t { | |
39 | public: | |
40 | entity_type_t _type; | |
41 | int64_t _num; | |
42 | ||
43 | public: | |
44 | static const int TYPE_MON = CEPH_ENTITY_TYPE_MON; | |
45 | static const int TYPE_MDS = CEPH_ENTITY_TYPE_MDS; | |
46 | static const int TYPE_OSD = CEPH_ENTITY_TYPE_OSD; | |
47 | static const int TYPE_CLIENT = CEPH_ENTITY_TYPE_CLIENT; | |
48 | static const int TYPE_MGR = CEPH_ENTITY_TYPE_MGR; | |
49 | ||
50 | static const int64_t NEW = -1; | |
51 | ||
52 | // cons | |
53 | entity_name_t() : _type(0), _num(0) { } | |
54 | entity_name_t(int t, int64_t n) : _type(t), _num(n) { } | |
11fdf7f2 | 55 | explicit entity_name_t(const ceph_entity_name &n) : |
7c673cae FG |
56 | _type(n.type), _num(n.num) { } |
57 | ||
58 | // static cons | |
59 | static entity_name_t MON(int64_t i=NEW) { return entity_name_t(TYPE_MON, i); } | |
60 | static entity_name_t MDS(int64_t i=NEW) { return entity_name_t(TYPE_MDS, i); } | |
61 | static entity_name_t OSD(int64_t i=NEW) { return entity_name_t(TYPE_OSD, i); } | |
62 | static entity_name_t CLIENT(int64_t i=NEW) { return entity_name_t(TYPE_CLIENT, i); } | |
63 | static entity_name_t MGR(int64_t i=NEW) { return entity_name_t(TYPE_MGR, i); } | |
11fdf7f2 | 64 | |
7c673cae FG |
65 | int64_t num() const { return _num; } |
66 | int type() const { return _type; } | |
67 | const char *type_str() const { | |
68 | return ceph_entity_type_name(type()); | |
69 | } | |
70 | ||
71 | bool is_new() const { return num() < 0; } | |
72 | ||
73 | bool is_client() const { return type() == TYPE_CLIENT; } | |
74 | bool is_mds() const { return type() == TYPE_MDS; } | |
75 | bool is_osd() const { return type() == TYPE_OSD; } | |
76 | bool is_mon() const { return type() == TYPE_MON; } | |
77 | bool is_mgr() const { return type() == TYPE_MGR; } | |
78 | ||
79 | operator ceph_entity_name() const { | |
20effc67 | 80 | ceph_entity_name n = { _type, ceph_le64(_num) }; |
7c673cae FG |
81 | return n; |
82 | } | |
83 | ||
20effc67 | 84 | bool parse(std::string_view s); |
7c673cae FG |
85 | |
86 | DENC(entity_name_t, v, p) { | |
87 | denc(v._type, p); | |
88 | denc(v._num, p); | |
89 | } | |
9f95a23c | 90 | void dump(ceph::Formatter *f) const; |
7c673cae | 91 | |
9f95a23c | 92 | static void generate_test_instances(std::list<entity_name_t*>& o); |
7c673cae FG |
93 | }; |
94 | WRITE_CLASS_DENC(entity_name_t) | |
95 | ||
11fdf7f2 | 96 | inline bool operator== (const entity_name_t& l, const entity_name_t& r) { |
7c673cae | 97 | return (l.type() == r.type()) && (l.num() == r.num()); } |
11fdf7f2 | 98 | inline bool operator!= (const entity_name_t& l, const entity_name_t& r) { |
7c673cae | 99 | return (l.type() != r.type()) || (l.num() != r.num()); } |
11fdf7f2 | 100 | inline bool operator< (const entity_name_t& l, const entity_name_t& r) { |
7c673cae FG |
101 | return (l.type() < r.type()) || (l.type() == r.type() && l.num() < r.num()); } |
102 | ||
103 | inline std::ostream& operator<<(std::ostream& out, const entity_name_t& addr) { | |
104 | //if (addr.is_namer()) return out << "namer"; | |
105 | if (addr.is_new() || addr.num() < 0) | |
106 | return out << addr.type_str() << ".?"; | |
107 | else | |
108 | return out << addr.type_str() << '.' << addr.num(); | |
109 | } | |
110 | inline std::ostream& operator<<(std::ostream& out, const ceph_entity_name& addr) { | |
11fdf7f2 | 111 | return out << entity_name_t{addr.type, static_cast<int64_t>(addr.num)}; |
7c673cae FG |
112 | } |
113 | ||
114 | namespace std { | |
115 | template<> struct hash< entity_name_t > | |
116 | { | |
117 | size_t operator()( const entity_name_t &m ) const | |
118 | { | |
119 | return rjhash32(m.type() ^ m.num()); | |
120 | } | |
121 | }; | |
122 | } // namespace std | |
123 | ||
7c673cae FG |
124 | // define a wire format for sockaddr that matches Linux's. |
125 | struct ceph_sockaddr_storage { | |
eafe8130 TL |
126 | ceph_le16 ss_family; |
127 | __u8 __ss_padding[128 - sizeof(ceph_le16)]; | |
7c673cae | 128 | |
9f95a23c | 129 | void encode(ceph::buffer::list& bl) const { |
7c673cae FG |
130 | struct ceph_sockaddr_storage ss = *this; |
131 | ss.ss_family = htons(ss.ss_family); | |
9f95a23c | 132 | ceph::encode_raw(ss, bl); |
7c673cae FG |
133 | } |
134 | ||
9f95a23c | 135 | void decode(ceph::buffer::list::const_iterator& bl) { |
7c673cae | 136 | struct ceph_sockaddr_storage ss; |
9f95a23c | 137 | ceph::decode_raw(ss, bl); |
7c673cae FG |
138 | ss.ss_family = ntohs(ss.ss_family); |
139 | *this = ss; | |
140 | } | |
141 | } __attribute__ ((__packed__)); | |
142 | WRITE_CLASS_ENCODER(ceph_sockaddr_storage) | |
143 | ||
11fdf7f2 TL |
144 | /* |
145 | * encode sockaddr.ss_family as network byte order | |
146 | */ | |
9f95a23c | 147 | static inline void encode(const sockaddr_storage& a, ceph::buffer::list& bl) { |
11fdf7f2 TL |
148 | #if defined(__linux__) |
149 | struct sockaddr_storage ss = a; | |
150 | ss.ss_family = htons(ss.ss_family); | |
9f95a23c | 151 | ceph::encode_raw(ss, bl); |
11fdf7f2 TL |
152 | #elif defined(__FreeBSD__) || defined(__APPLE__) |
153 | ceph_sockaddr_storage ss{}; | |
154 | auto src = (unsigned char const *)&a; | |
155 | auto dst = (unsigned char *)&ss; | |
156 | src += sizeof(a.ss_len); | |
157 | ss.ss_family = a.ss_family; | |
158 | src += sizeof(a.ss_family); | |
159 | dst += sizeof(ss.ss_family); | |
160 | const auto copy_size = std::min((unsigned char*)(&a + 1) - src, | |
161 | (unsigned char*)(&ss + 1) - dst); | |
162 | ::memcpy(dst, src, copy_size); | |
163 | encode(ss, bl); | |
164 | #else | |
f67539c2 | 165 | ceph_sockaddr_storage ss; |
11fdf7f2 | 166 | ::memset(&ss, '\0', sizeof(ss)); |
f67539c2 | 167 | ::memcpy(&ss, &a, std::min(sizeof(ss), sizeof(a))); |
11fdf7f2 TL |
168 | encode(ss, bl); |
169 | #endif | |
170 | } | |
9f95a23c TL |
171 | static inline void decode(sockaddr_storage& a, |
172 | ceph::buffer::list::const_iterator& bl) { | |
11fdf7f2 | 173 | #if defined(__linux__) |
9f95a23c | 174 | ceph::decode_raw(a, bl); |
11fdf7f2 TL |
175 | a.ss_family = ntohs(a.ss_family); |
176 | #elif defined(__FreeBSD__) || defined(__APPLE__) | |
177 | ceph_sockaddr_storage ss{}; | |
178 | decode(ss, bl); | |
179 | auto src = (unsigned char const *)&ss; | |
180 | auto dst = (unsigned char *)&a; | |
181 | a.ss_len = 0; | |
182 | dst += sizeof(a.ss_len); | |
183 | a.ss_family = ss.ss_family; | |
184 | src += sizeof(ss.ss_family); | |
185 | dst += sizeof(a.ss_family); | |
186 | auto const copy_size = std::min((unsigned char*)(&ss + 1) - src, | |
187 | (unsigned char*)(&a + 1) - dst); | |
188 | ::memcpy(dst, src, copy_size); | |
189 | #else | |
190 | ceph_sockaddr_storage ss{}; | |
191 | decode(ss, bl); | |
192 | ::memcpy(&a, &ss, std::min(sizeof(ss), sizeof(a))); | |
193 | #endif | |
194 | } | |
195 | ||
196 | /* | |
197 | * an entity's network address. | |
198 | * includes a random value that prevents it from being reused. | |
199 | * thus identifies a particular process instance. | |
200 | * ipv4 for now. | |
201 | */ | |
7c673cae FG |
202 | struct entity_addr_t { |
203 | typedef enum { | |
204 | TYPE_NONE = 0, | |
205 | TYPE_LEGACY = 1, ///< legacy msgr1 protocol (ceph jewel and older) | |
206 | TYPE_MSGR2 = 2, ///< msgr2 protocol (new in ceph kraken) | |
11fdf7f2 | 207 | TYPE_ANY = 3, ///< ambiguous |
7c673cae | 208 | } type_t; |
11fdf7f2 TL |
209 | static const type_t TYPE_DEFAULT = TYPE_MSGR2; |
210 | static std::string_view get_type_name(int t) { | |
7c673cae FG |
211 | switch (t) { |
212 | case TYPE_NONE: return "none"; | |
11fdf7f2 TL |
213 | case TYPE_LEGACY: return "v1"; |
214 | case TYPE_MSGR2: return "v2"; | |
215 | case TYPE_ANY: return "any"; | |
7c673cae FG |
216 | default: return "???"; |
217 | } | |
218 | }; | |
219 | ||
220 | __u32 type; | |
221 | __u32 nonce; | |
222 | union { | |
223 | sockaddr sa; | |
224 | sockaddr_in sin; | |
225 | sockaddr_in6 sin6; | |
226 | } u; | |
227 | ||
11fdf7f2 | 228 | entity_addr_t() : type(0), nonce(0) { |
7c673cae FG |
229 | memset(&u, 0, sizeof(u)); |
230 | } | |
231 | entity_addr_t(__u32 _type, __u32 _nonce) : type(_type), nonce(_nonce) { | |
232 | memset(&u, 0, sizeof(u)); | |
233 | } | |
234 | explicit entity_addr_t(const ceph_entity_addr &o) { | |
235 | type = o.type; | |
236 | nonce = o.nonce; | |
237 | memcpy(&u, &o.in_addr, sizeof(u)); | |
238 | #if !defined(__FreeBSD__) | |
239 | u.sa.sa_family = ntohs(u.sa.sa_family); | |
240 | #endif | |
241 | } | |
242 | ||
243 | uint32_t get_type() const { return type; } | |
244 | void set_type(uint32_t t) { type = t; } | |
11fdf7f2 TL |
245 | bool is_legacy() const { return type == TYPE_LEGACY; } |
246 | bool is_msgr2() const { return type == TYPE_MSGR2; } | |
247 | bool is_any() const { return type == TYPE_ANY; } | |
7c673cae FG |
248 | |
249 | __u32 get_nonce() const { return nonce; } | |
250 | void set_nonce(__u32 n) { nonce = n; } | |
251 | ||
252 | int get_family() const { | |
253 | return u.sa.sa_family; | |
254 | } | |
255 | void set_family(int f) { | |
256 | u.sa.sa_family = f; | |
257 | } | |
258 | ||
11fdf7f2 TL |
259 | bool is_ipv4() const { |
260 | return u.sa.sa_family == AF_INET; | |
261 | } | |
262 | bool is_ipv6() const { | |
263 | return u.sa.sa_family == AF_INET6; | |
264 | } | |
265 | ||
7c673cae FG |
266 | sockaddr_in &in4_addr() { |
267 | return u.sin; | |
268 | } | |
269 | const sockaddr_in &in4_addr() const{ | |
270 | return u.sin; | |
271 | } | |
272 | sockaddr_in6 &in6_addr(){ | |
273 | return u.sin6; | |
274 | } | |
275 | const sockaddr_in6 &in6_addr() const{ | |
276 | return u.sin6; | |
277 | } | |
278 | const sockaddr *get_sockaddr() const { | |
279 | return &u.sa; | |
280 | } | |
281 | size_t get_sockaddr_len() const { | |
282 | switch (u.sa.sa_family) { | |
283 | case AF_INET: | |
284 | return sizeof(u.sin); | |
285 | case AF_INET6: | |
286 | return sizeof(u.sin6); | |
287 | } | |
288 | return sizeof(u); | |
289 | } | |
290 | bool set_sockaddr(const struct sockaddr *sa) | |
291 | { | |
292 | switch (sa->sa_family) { | |
293 | case AF_INET: | |
11fdf7f2 TL |
294 | // pre-zero, since we're only copying a portion of the source |
295 | memset(&u, 0, sizeof(u)); | |
7c673cae FG |
296 | memcpy(&u.sin, sa, sizeof(u.sin)); |
297 | break; | |
298 | case AF_INET6: | |
11fdf7f2 TL |
299 | // pre-zero, since we're only copying a portion of the source |
300 | memset(&u, 0, sizeof(u)); | |
7c673cae FG |
301 | memcpy(&u.sin6, sa, sizeof(u.sin6)); |
302 | break; | |
11fdf7f2 TL |
303 | case AF_UNSPEC: |
304 | memset(&u, 0, sizeof(u)); | |
305 | break; | |
7c673cae FG |
306 | default: |
307 | return false; | |
308 | } | |
309 | return true; | |
310 | } | |
311 | ||
312 | sockaddr_storage get_sockaddr_storage() const { | |
313 | sockaddr_storage ss; | |
314 | memcpy(&ss, &u, sizeof(u)); | |
315 | memset((char*)&ss + sizeof(u), 0, sizeof(ss) - sizeof(u)); | |
316 | return ss; | |
317 | } | |
318 | ||
319 | void set_in4_quad(int pos, int val) { | |
320 | u.sin.sin_family = AF_INET; | |
321 | unsigned char *ipq = (unsigned char*)&u.sin.sin_addr.s_addr; | |
322 | ipq[pos] = val; | |
323 | } | |
324 | void set_port(int port) { | |
325 | switch (u.sa.sa_family) { | |
326 | case AF_INET: | |
327 | u.sin.sin_port = htons(port); | |
328 | break; | |
329 | case AF_INET6: | |
330 | u.sin6.sin6_port = htons(port); | |
331 | break; | |
332 | default: | |
333 | ceph_abort(); | |
334 | } | |
335 | } | |
336 | int get_port() const { | |
337 | switch (u.sa.sa_family) { | |
338 | case AF_INET: | |
339 | return ntohs(u.sin.sin_port); | |
7c673cae FG |
340 | case AF_INET6: |
341 | return ntohs(u.sin6.sin6_port); | |
7c673cae FG |
342 | } |
343 | return 0; | |
344 | } | |
345 | ||
346 | operator ceph_entity_addr() const { | |
347 | ceph_entity_addr a; | |
348 | a.type = 0; | |
349 | a.nonce = nonce; | |
350 | a.in_addr = get_sockaddr_storage(); | |
351 | #if !defined(__FreeBSD__) | |
352 | a.in_addr.ss_family = htons(a.in_addr.ss_family); | |
353 | #endif | |
354 | return a; | |
355 | } | |
356 | ||
357 | bool probably_equals(const entity_addr_t &o) const { | |
358 | if (get_port() != o.get_port()) | |
359 | return false; | |
360 | if (get_nonce() != o.get_nonce()) | |
361 | return false; | |
362 | if (is_blank_ip() || o.is_blank_ip()) | |
363 | return true; | |
364 | if (memcmp(&u, &o.u, sizeof(u)) == 0) | |
365 | return true; | |
366 | return false; | |
367 | } | |
11fdf7f2 | 368 | |
7c673cae FG |
369 | bool is_same_host(const entity_addr_t &o) const { |
370 | if (u.sa.sa_family != o.u.sa.sa_family) | |
371 | return false; | |
372 | if (u.sa.sa_family == AF_INET) | |
373 | return u.sin.sin_addr.s_addr == o.u.sin.sin_addr.s_addr; | |
374 | if (u.sa.sa_family == AF_INET6) | |
375 | return memcmp(u.sin6.sin6_addr.s6_addr, | |
376 | o.u.sin6.sin6_addr.s6_addr, | |
377 | sizeof(u.sin6.sin6_addr.s6_addr)) == 0; | |
378 | return false; | |
379 | } | |
380 | ||
381 | bool is_blank_ip() const { | |
382 | switch (u.sa.sa_family) { | |
383 | case AF_INET: | |
384 | return u.sin.sin_addr.s_addr == INADDR_ANY; | |
385 | case AF_INET6: | |
386 | return memcmp(&u.sin6.sin6_addr, &in6addr_any, sizeof(in6addr_any)) == 0; | |
387 | default: | |
388 | return true; | |
389 | } | |
390 | } | |
391 | ||
392 | bool is_ip() const { | |
393 | switch (u.sa.sa_family) { | |
394 | case AF_INET: | |
395 | case AF_INET6: | |
396 | return true; | |
397 | default: | |
398 | return false; | |
399 | } | |
400 | } | |
401 | ||
11fdf7f2 | 402 | std::string ip_only_to_str() const; |
7c673cae | 403 | |
11fdf7f2 | 404 | std::string get_legacy_str() const { |
9f95a23c | 405 | std::ostringstream ss; |
11fdf7f2 TL |
406 | ss << get_sockaddr() << "/" << get_nonce(); |
407 | return ss.str(); | |
408 | } | |
409 | ||
20effc67 TL |
410 | bool parse(const std::string_view s, int default_type=TYPE_DEFAULT); |
411 | bool parse(const char *s, const char **end = 0, int default_type=TYPE_DEFAULT); | |
11fdf7f2 | 412 | |
9f95a23c | 413 | void decode_legacy_addr_after_marker(ceph::buffer::list::const_iterator& bl) |
7c673cae | 414 | { |
11fdf7f2 | 415 | using ceph::decode; |
7c673cae FG |
416 | __u8 marker; |
417 | __u16 rest; | |
11fdf7f2 TL |
418 | decode(marker, bl); |
419 | decode(rest, bl); | |
420 | decode(nonce, bl); | |
7c673cae | 421 | sockaddr_storage ss; |
11fdf7f2 | 422 | decode(ss, bl); |
7c673cae | 423 | set_sockaddr((sockaddr*)&ss); |
11fdf7f2 TL |
424 | if (get_family() == AF_UNSPEC) { |
425 | type = TYPE_NONE; | |
426 | } else { | |
427 | type = TYPE_LEGACY; | |
428 | } | |
7c673cae FG |
429 | } |
430 | ||
431 | // Right now, these only deal with sockaddr_storage that have only family and content. | |
432 | // Apparently on BSD there is also an ss_len that we need to handle; this requires | |
433 | // broader study | |
434 | ||
9f95a23c | 435 | void encode(ceph::buffer::list& bl, uint64_t features) const { |
11fdf7f2 | 436 | using ceph::encode; |
7c673cae | 437 | if ((features & CEPH_FEATURE_MSG_ADDR2) == 0) { |
11fdf7f2 TL |
438 | encode((__u32)0, bl); |
439 | encode(nonce, bl); | |
7c673cae | 440 | sockaddr_storage ss = get_sockaddr_storage(); |
11fdf7f2 | 441 | encode(ss, bl); |
7c673cae FG |
442 | return; |
443 | } | |
11fdf7f2 | 444 | encode((__u8)1, bl); |
7c673cae | 445 | ENCODE_START(1, 1, bl); |
11fdf7f2 TL |
446 | if (HAVE_FEATURE(features, SERVER_NAUTILUS)) { |
447 | encode(type, bl); | |
448 | } else { | |
449 | // map any -> legacy for old clients. this is primary for the benefit | |
f67539c2 | 450 | // of OSDMap's blocklist, but is reasonable in general since any: is |
11fdf7f2 TL |
451 | // meaningless for pre-nautilus clients or daemons. |
452 | auto t = type; | |
453 | if (t == TYPE_ANY) { | |
454 | t = TYPE_LEGACY; | |
455 | } | |
456 | encode(t, bl); | |
457 | } | |
458 | encode(nonce, bl); | |
7c673cae | 459 | __u32 elen = get_sockaddr_len(); |
eafe8130 TL |
460 | #if (__FreeBSD__) || defined(__APPLE__) |
461 | elen -= sizeof(u.sa.sa_len); | |
462 | #endif | |
11fdf7f2 | 463 | encode(elen, bl); |
7c673cae | 464 | if (elen) { |
eafe8130 TL |
465 | uint16_t ss_family = u.sa.sa_family; |
466 | ||
11fdf7f2 | 467 | encode(ss_family, bl); |
eafe8130 TL |
468 | elen -= sizeof(u.sa.sa_family); |
469 | bl.append(u.sa.sa_data, elen); | |
7c673cae FG |
470 | } |
471 | ENCODE_FINISH(bl); | |
472 | } | |
9f95a23c | 473 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 | 474 | using ceph::decode; |
7c673cae | 475 | __u8 marker; |
11fdf7f2 | 476 | decode(marker, bl); |
7c673cae FG |
477 | if (marker == 0) { |
478 | decode_legacy_addr_after_marker(bl); | |
479 | return; | |
480 | } | |
481 | if (marker != 1) | |
9f95a23c | 482 | throw ceph::buffer::malformed_input("entity_addr_t marker != 1"); |
7c673cae | 483 | DECODE_START(1, bl); |
11fdf7f2 TL |
484 | decode(type, bl); |
485 | decode(nonce, bl); | |
7c673cae | 486 | __u32 elen; |
11fdf7f2 | 487 | decode(elen, bl); |
7c673cae | 488 | if (elen) { |
a8e16298 TL |
489 | #if defined(__FreeBSD__) || defined(__APPLE__) |
490 | u.sa.sa_len = 0; | |
eafe8130 TL |
491 | #endif |
492 | uint16_t ss_family; | |
a8e16298 | 493 | if (elen < sizeof(ss_family)) { |
f67539c2 | 494 | throw ceph::buffer::malformed_input("elen smaller than family len"); |
a8e16298 | 495 | } |
11fdf7f2 | 496 | decode(ss_family, bl); |
a8e16298 TL |
497 | u.sa.sa_family = ss_family; |
498 | elen -= sizeof(ss_family); | |
499 | if (elen > get_sockaddr_len() - sizeof(u.sa.sa_family)) { | |
f67539c2 | 500 | throw ceph::buffer::malformed_input("elen exceeds sockaddr len"); |
a8e16298 TL |
501 | } |
502 | bl.copy(elen, u.sa.sa_data); | |
7c673cae FG |
503 | } |
504 | DECODE_FINISH(bl); | |
505 | } | |
506 | ||
9f95a23c | 507 | void dump(ceph::Formatter *f) const; |
7c673cae | 508 | |
9f95a23c | 509 | static void generate_test_instances(std::list<entity_addr_t*>& o); |
7c673cae FG |
510 | }; |
511 | WRITE_CLASS_ENCODER_FEATURES(entity_addr_t) | |
512 | ||
9f95a23c | 513 | std::ostream& operator<<(std::ostream& out, const entity_addr_t &addr); |
7c673cae FG |
514 | |
515 | inline bool operator==(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) == 0; } | |
516 | inline bool operator!=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) != 0; } | |
517 | inline bool operator<(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) < 0; } | |
518 | inline bool operator<=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) <= 0; } | |
519 | inline bool operator>(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) > 0; } | |
520 | inline bool operator>=(const entity_addr_t& a, const entity_addr_t& b) { return memcmp(&a, &b, sizeof(a)) >= 0; } | |
521 | ||
522 | namespace std { | |
9f95a23c TL |
523 | template<> struct hash<entity_addr_t> { |
524 | size_t operator()( const entity_addr_t& x ) const { | |
525 | static blobhash H; | |
526 | return H(&x, sizeof(x)); | |
527 | } | |
528 | }; | |
7c673cae FG |
529 | } // namespace std |
530 | ||
531 | struct entity_addrvec_t { | |
9f95a23c | 532 | std::vector<entity_addr_t> v; |
7c673cae | 533 | |
11fdf7f2 TL |
534 | entity_addrvec_t() {} |
535 | explicit entity_addrvec_t(const entity_addr_t& a) : v({ a }) {} | |
536 | ||
7c673cae FG |
537 | unsigned size() const { return v.size(); } |
538 | bool empty() const { return v.empty(); } | |
539 | ||
11fdf7f2 | 540 | entity_addr_t legacy_addr() const { |
f67539c2 | 541 | return addr_of_type(entity_addr_t::TYPE_LEGACY); |
11fdf7f2 TL |
542 | } |
543 | entity_addr_t as_legacy_addr() const { | |
544 | for (auto& a : v) { | |
545 | if (a.is_legacy()) { | |
546 | return a; | |
547 | } | |
548 | if (a.is_any()) { | |
549 | auto b = a; | |
550 | b.set_type(entity_addr_t::TYPE_LEGACY); | |
551 | return b; | |
552 | } | |
553 | } | |
554 | // hrm... lie! | |
555 | auto a = front(); | |
556 | a.set_type(entity_addr_t::TYPE_LEGACY); | |
557 | return a; | |
558 | } | |
559 | entity_addr_t front() const { | |
560 | if (!v.empty()) { | |
561 | return v.front(); | |
562 | } | |
563 | return entity_addr_t(); | |
564 | } | |
565 | entity_addr_t legacy_or_front_addr() const { | |
566 | for (auto& a : v) { | |
567 | if (a.type == entity_addr_t::TYPE_LEGACY) { | |
568 | return a; | |
569 | } | |
570 | } | |
f67539c2 | 571 | return front(); |
11fdf7f2 | 572 | } |
9f95a23c | 573 | std::string get_legacy_str() const { |
11fdf7f2 TL |
574 | return legacy_or_front_addr().get_legacy_str(); |
575 | } | |
576 | ||
577 | entity_addr_t msgr2_addr() const { | |
f67539c2 | 578 | return addr_of_type(entity_addr_t::TYPE_MSGR2); |
11fdf7f2 TL |
579 | } |
580 | bool has_msgr2() const { | |
581 | for (auto& a : v) { | |
582 | if (a.is_msgr2()) { | |
583 | return true; | |
584 | } | |
585 | } | |
586 | return false; | |
587 | } | |
588 | ||
f67539c2 TL |
589 | entity_addr_t pick_addr(uint32_t type) const { |
590 | entity_addr_t picked_addr; | |
591 | switch (type) { | |
592 | case entity_addr_t::TYPE_LEGACY: | |
593 | [[fallthrough]]; | |
594 | case entity_addr_t::TYPE_MSGR2: | |
595 | picked_addr = addr_of_type(type); | |
596 | break; | |
597 | case entity_addr_t::TYPE_ANY: | |
598 | return front(); | |
599 | default: | |
600 | return {}; | |
601 | } | |
602 | if (!picked_addr.is_blank_ip()) { | |
603 | return picked_addr; | |
604 | } else { | |
605 | return addr_of_type(entity_addr_t::TYPE_ANY); | |
606 | } | |
607 | } | |
608 | ||
609 | entity_addr_t addr_of_type(uint32_t type) const { | |
610 | for (auto &a : v) { | |
611 | if (a.type == type) { | |
612 | return a; | |
613 | } | |
614 | } | |
615 | return entity_addr_t(); | |
616 | } | |
617 | ||
11fdf7f2 TL |
618 | bool parse(const char *s, const char **end = 0); |
619 | ||
9f95a23c | 620 | void get_ports(std::set<int> *ports) const { |
11fdf7f2 TL |
621 | for (auto& a : v) { |
622 | ports->insert(a.get_port()); | |
623 | } | |
624 | } | |
9f95a23c TL |
625 | std::set<int> get_ports() const { |
626 | std::set<int> r; | |
11fdf7f2 TL |
627 | get_ports(&r); |
628 | return r; | |
629 | } | |
630 | ||
9f95a23c TL |
631 | void encode(ceph::buffer::list& bl, uint64_t features) const; |
632 | void decode(ceph::buffer::list::const_iterator& bl); | |
633 | void dump(ceph::Formatter *f) const; | |
634 | static void generate_test_instances(std::list<entity_addrvec_t*>& ls); | |
11fdf7f2 TL |
635 | |
636 | bool legacy_equals(const entity_addrvec_t& o) const { | |
637 | if (v == o.v) { | |
638 | return true; | |
639 | } | |
640 | if (v.size() == 1 && | |
641 | front().is_legacy() && | |
642 | front() == o.legacy_addr()) { | |
643 | return true; | |
644 | } | |
645 | if (o.v.size() == 1 && | |
646 | o.front().is_legacy() && | |
647 | o.front() == legacy_addr()) { | |
648 | return true; | |
649 | } | |
650 | return false; | |
651 | } | |
652 | ||
653 | bool probably_equals(const entity_addrvec_t& o) const { | |
654 | for (unsigned i = 0; i < v.size(); ++i) { | |
655 | if (!v[i].probably_equals(o.v[i])) { | |
656 | return false; | |
657 | } | |
658 | } | |
659 | return true; | |
660 | } | |
661 | bool contains(const entity_addr_t& a) const { | |
662 | for (auto& i : v) { | |
663 | if (a == i) { | |
664 | return true; | |
665 | } | |
666 | } | |
667 | return false; | |
668 | } | |
669 | bool is_same_host(const entity_addr_t& a) const { | |
670 | for (auto& i : v) { | |
671 | if (i.is_same_host(a)) { | |
672 | return true; | |
673 | } | |
674 | } | |
675 | return false; | |
676 | } | |
677 | ||
9f95a23c | 678 | friend std::ostream& operator<<(std::ostream& out, const entity_addrvec_t& av) { |
11fdf7f2 TL |
679 | if (av.v.empty()) { |
680 | return out; | |
681 | } else if (av.v.size() == 1) { | |
682 | return out << av.v[0]; | |
683 | } else { | |
684 | return out << av.v; | |
685 | } | |
686 | } | |
687 | ||
688 | friend bool operator==(const entity_addrvec_t& l, const entity_addrvec_t& r) { | |
689 | return l.v == r.v; | |
690 | } | |
691 | friend bool operator!=(const entity_addrvec_t& l, const entity_addrvec_t& r) { | |
692 | return l.v != r.v; | |
693 | } | |
694 | friend bool operator<(const entity_addrvec_t& l, const entity_addrvec_t& r) { | |
695 | return l.v < r.v; // see lexicographical_compare() | |
696 | } | |
20effc67 TL |
697 | friend bool operator>(const entity_addrvec_t& l, const entity_addrvec_t& r) { |
698 | return l.v > r.v; // see lexicographical_compare() | |
699 | } | |
7c673cae FG |
700 | }; |
701 | WRITE_CLASS_ENCODER_FEATURES(entity_addrvec_t); | |
702 | ||
11fdf7f2 | 703 | namespace std { |
9f95a23c TL |
704 | template<> struct hash<entity_addrvec_t> { |
705 | size_t operator()( const entity_addrvec_t& x) const { | |
706 | static blobhash H; | |
707 | size_t r = 0; | |
708 | for (auto& i : x.v) { | |
709 | r += H((const char*)&i, sizeof(i)); | |
11fdf7f2 | 710 | } |
9f95a23c TL |
711 | return r; |
712 | } | |
713 | }; | |
11fdf7f2 TL |
714 | } // namespace std |
715 | ||
7c673cae FG |
716 | /* |
717 | * a particular entity instance | |
718 | */ | |
719 | struct entity_inst_t { | |
720 | entity_name_t name; | |
721 | entity_addr_t addr; | |
722 | entity_inst_t() {} | |
723 | entity_inst_t(entity_name_t n, const entity_addr_t& a) : name(n), addr(a) {} | |
724 | // cppcheck-suppress noExplicitConstructor | |
725 | entity_inst_t(const ceph_entity_inst& i) : name(i.name), addr(i.addr) { } | |
726 | entity_inst_t(const ceph_entity_name& n, const ceph_entity_addr &a) : name(n), addr(a) {} | |
727 | operator ceph_entity_inst() { | |
728 | ceph_entity_inst i = {name, addr}; | |
729 | return i; | |
730 | } | |
731 | ||
9f95a23c | 732 | void encode(ceph::buffer::list& bl, uint64_t features) const { |
11fdf7f2 TL |
733 | using ceph::encode; |
734 | encode(name, bl); | |
735 | encode(addr, bl, features); | |
7c673cae | 736 | } |
9f95a23c | 737 | void decode(ceph::buffer::list::const_iterator& bl) { |
11fdf7f2 TL |
738 | using ceph::decode; |
739 | decode(name, bl); | |
740 | decode(addr, bl); | |
7c673cae FG |
741 | } |
742 | ||
9f95a23c TL |
743 | void dump(ceph::Formatter *f) const; |
744 | static void generate_test_instances(std::list<entity_inst_t*>& o); | |
7c673cae FG |
745 | }; |
746 | WRITE_CLASS_ENCODER_FEATURES(entity_inst_t) | |
747 | ||
748 | ||
11fdf7f2 | 749 | inline bool operator==(const entity_inst_t& a, const entity_inst_t& b) { |
7c673cae FG |
750 | return a.name == b.name && a.addr == b.addr; |
751 | } | |
11fdf7f2 | 752 | inline bool operator!=(const entity_inst_t& a, const entity_inst_t& b) { |
7c673cae FG |
753 | return a.name != b.name || a.addr != b.addr; |
754 | } | |
11fdf7f2 | 755 | inline bool operator<(const entity_inst_t& a, const entity_inst_t& b) { |
7c673cae FG |
756 | return a.name < b.name || (a.name == b.name && a.addr < b.addr); |
757 | } | |
758 | inline bool operator<=(const entity_inst_t& a, const entity_inst_t& b) { | |
759 | return a.name < b.name || (a.name == b.name && a.addr <= b.addr); | |
760 | } | |
761 | inline bool operator>(const entity_inst_t& a, const entity_inst_t& b) { return b < a; } | |
762 | inline bool operator>=(const entity_inst_t& a, const entity_inst_t& b) { return b <= a; } | |
763 | ||
764 | namespace std { | |
765 | template<> struct hash< entity_inst_t > | |
766 | { | |
767 | size_t operator()( const entity_inst_t& x ) const | |
768 | { | |
769 | static hash< entity_name_t > H; | |
770 | static hash< entity_addr_t > I; | |
771 | return H(x.name) ^ I(x.addr); | |
772 | } | |
773 | }; | |
774 | } // namespace std | |
775 | ||
776 | ||
9f95a23c | 777 | inline std::ostream& operator<<(std::ostream& out, const entity_inst_t &i) |
7c673cae FG |
778 | { |
779 | return out << i.name << " " << i.addr; | |
780 | } | |
9f95a23c | 781 | inline std::ostream& operator<<(std::ostream& out, const ceph_entity_inst &i) |
7c673cae FG |
782 | { |
783 | entity_inst_t n = i; | |
784 | return out << n; | |
785 | } | |
786 | ||
787 | #endif |