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