Robust Distributed System Nucleus (rDSN)  ver 1.0.0
address.h
1 /*
2  * The MIT License (MIT)
3  *
4  * Copyright (c) 2015 Microsoft Corporation
5  *
6  * -=- Robust Distributed System Nucleus (rDSN) -=-
7  *
8  * Permission is hereby granted, free of charge, to any person obtaining a copy
9  * of this software and associated documentation files (the "Software"), to deal
10  * in the Software without restriction, including without limitation the rights
11  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
12  * copies of the Software, and to permit persons to whom the Software is
13  * furnished to do so, subject to the following conditions:
14  *
15  * The above copyright notice and this permission notice shall be included in
16  * all copies or substantial portions of the Software.
17  *
18  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
19  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
20  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
21  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
22  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
23  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24  * THE SOFTWARE.
25  */
26 
27 /*
28  * Description:
29  * define address helper routines around dsn_address_t structure
30  *
31  * Revision history:
32  * July, 2015, @imzhenyu (Zhenyu Guo), first version
33  * Aug., 2015, @imzhenyu (Zhenyu Guo), add group and uri address support
34  * xxxx-xx-xx, author, fix bug about xxx
35  */
36 
37 # pragma once
38 
39 # include <dsn/service_api_c.h>
40 # include <dsn/utility/autoref_ptr.h>
41 # include <unordered_map>
42 # include <unordered_set>
43 # include <vector>
44 # include <cstring> // for strcmp()
45 # include <string>
46 # include <cstdlib>
47 
48 #ifdef DSN_USE_THRIFT_SERIALIZATION
49 # include <thrift/protocol/TProtocol.h>
50 #endif
51 
52 namespace dsn
53 {
58  class rpc_group_address;
59  class rpc_uri_address;
60 
62  {
63  public:
64  ~rpc_address() { clear(); }
65 
66  rpc_address(uint32_t ip, uint16_t port);
67  rpc_address(const char* host, uint16_t port);
68 
69  void assign_ipv4(uint32_t ip, uint16_t port);
70  void assign_ipv4(const char* host, uint16_t port);
71  void assign_ipv4_local_address(const char* card_interface, uint16_t port);
72  void assign_uri(dsn_uri_t uri);
73  void assign_group(dsn_group_t g);
74 
75  rpc_address();
76  rpc_address(const rpc_address& addr);
78  rpc_address& operator=(dsn_address_t addr);
79 
80  const char* to_string() const;
81  std::string to_std_string() const;
82  bool from_string_ipv4(const char* s);
83  dsn_host_type_t type() const { return (dsn_host_type_t)_addr.u.v4.type; }
84  dsn_address_t c_addr() const { return _addr; }
85  dsn_address_t* c_addr_ptr() { return &_addr; }
86  uint32_t ip() const { return (uint32_t)_addr.u.v4.ip; }
87  uint16_t port() const { return (uint16_t)_addr.u.v4.port; }
88  rpc_group_address* group_address() const { return (rpc_group_address*)(uintptr_t)_addr.u.group.group; }
89  dsn_group_t group_handle() const { return (dsn_group_t)(uintptr_t)_addr.u.group.group; }
90  rpc_uri_address* uri_address() const { return (rpc_uri_address*)(uintptr_t)_addr.u.uri.uri; }
91  dsn_uri_t uri_handle() const { return (dsn_group_t)(uintptr_t)_addr.u.uri.uri; }
92  bool is_invalid() const { return _addr.u.v4.type == HOST_TYPE_INVALID; }
93  void set_invalid() { clear(); }
94 
95  bool operator == (::dsn::rpc_address r) const;
96  bool operator != (::dsn::rpc_address r) const;
97  bool operator < (::dsn::rpc_address r) const;
98 
99 #ifdef DSN_USE_THRIFT_SERIALIZATION
100  uint32_t read(::apache::thrift::protocol::TProtocol* iprot);
101  uint32_t write(::apache::thrift::protocol::TProtocol* oprot) const;
102 #endif
103  private:
104  void clear();
105 
106  private:
107  dsn_address_t _addr;
108  };
109 
111  {
112  public:
113  // dsn://mycluster/myapp, or host-name:port
114  url_host_address(const char* url_or_host_port);
115  url_host_address() {}
116 
117  private:
118  std::string _url_host; //< make sure the buffer is valid
119  };
120 
121  // ------------- inline implementation -------------------
122  inline rpc_address::rpc_address(uint32_t ip, uint16_t port)
123  {
124  assign_ipv4(ip, port);
125 
126  static_assert (sizeof(rpc_address) == sizeof(dsn_address_t),
127  "make sure rpc_address does not add new payload to dsn_address_t to keep it sizeof(uint64_t)");
128  }
129 
130  inline rpc_address::rpc_address(const char* host, uint16_t port)
131  {
132  assign_ipv4(host, port);
133  }
134 
135  inline void rpc_address::assign_ipv4(uint32_t ip, uint16_t port)
136  {
137  clear();
138  _addr.u.v4.type = HOST_TYPE_IPV4;
139  _addr.u.v4.ip = ip;
140  _addr.u.v4.port = port;
141  }
142 
143  inline void rpc_address::assign_ipv4(const char* host, uint16_t port)
144  {
145  clear();
146  _addr.u.v4.type = HOST_TYPE_IPV4;
147  _addr.u.v4.ip = dsn_ipv4_from_host(host);
148  _addr.u.v4.port = port;
149  }
150 
151  inline void rpc_address::assign_ipv4_local_address(const char* network_interface, uint16_t port)
152  {
153  clear();
154  _addr.u.v4.type = HOST_TYPE_IPV4;
155  _addr.u.v4.ip = dsn_ipv4_local(network_interface);
156  _addr.u.v4.port = port;
157  }
158 
159  inline void rpc_address::assign_uri(dsn_uri_t uri)
160  {
161  clear();
162  _addr.u.v4.type = HOST_TYPE_URI;
163  _addr.u.uri.uri = (uint64_t)uri;
164  }
165 
166  inline void rpc_address::assign_group(dsn_group_t g)
167  {
168  clear();
169  _addr.u.v4.type = HOST_TYPE_GROUP;
170  _addr.u.group.group = (uint64_t)g;
171  }
172 
173  inline rpc_address::rpc_address()
174  {
175  _addr.u.value = 0;
176  _addr.u.v4.type = HOST_TYPE_INVALID;
177  }
178 
179  inline rpc_address::rpc_address(const rpc_address& addr)
180  {
181  _addr = addr._addr;
182  }
183 
184  inline rpc_address::rpc_address(dsn_address_t addr)
185  {
186  _addr = addr;
187  }
188 
189  inline rpc_address& rpc_address::operator=(dsn_address_t addr)
190  {
191  _addr = addr;
192  return *this;
193  }
194 
195  inline bool rpc_address::operator == (::dsn::rpc_address r) const
196  {
197  if (_addr.u.v4.type != r.type())
198  return false;
199 
200  switch (_addr.u.v4.type)
201  {
202  case HOST_TYPE_IPV4:
203  return _addr.u.v4.ip == r.ip() && _addr.u.v4.port == r.port();
204  case HOST_TYPE_URI:
205  return strcmp(to_string(), r.to_string()) == 0;
206  case HOST_TYPE_GROUP:
207  return _addr.u.group.group == r.c_addr().u.group.group;
208  default:
209  return true;
210  }
211  }
212 
213  inline bool rpc_address::operator != (::dsn::rpc_address r) const
214  {
215  return !(*this == r);
216  }
217 
218  inline bool rpc_address::operator < (::dsn::rpc_address r) const
219  {
220  if (_addr.u.v4.type != r.type())
221  return _addr.u.v4.type < r.type();
222 
223  switch (_addr.u.v4.type)
224  {
225  case HOST_TYPE_IPV4:
226  return _addr.u.v4.ip < r.ip() || (_addr.u.v4.ip == r.ip() && _addr.u.v4.port < r.port());
227  case HOST_TYPE_URI:
228  return strcmp(to_string(), r.to_string()) < 0;
229  case HOST_TYPE_GROUP:
230  return _addr.u.group.group < r.c_addr().u.group.group;
231  default:
232  return true;
233  }
234  }
235 
236  inline void rpc_address::clear()
237  {
238  _addr.u.value = 0;
239  }
240 
241  inline const char* rpc_address::to_string() const
242  {
243  return dsn_address_to_string(_addr);
244  }
245 
246  inline std::string rpc_address::to_std_string() const
247  {
248  return std::string(to_string());
249  }
250 
251  inline bool rpc_address::from_string_ipv4(const char* s)
252  {
253  std::string str = std::string(s);
254  auto pos = str.find_last_of(':');
255  if (pos == std::string::npos)
256  return false;
257  else
258  {
259  auto host = str.substr(0, pos);
260  auto port = atoi(str.substr(pos + 1).c_str());
261  assign_ipv4(host.c_str(), (uint16_t)port);
262  return true;
263  }
264  }
265 
266  inline url_host_address::url_host_address(const char* url_or_host_port)
267  {
268  std::string s(url_or_host_port);
269  auto sp = s.find(':');
270  if (sp != std::string::npos)
271  {
272  uint16_t port = (uint16_t)atoi(s.substr(sp + 1).c_str());
273  if (port == 0)
274  {
275  _url_host = std::string(url_or_host_port);
276  assign_uri(dsn_uri_build(_url_host.c_str()));
277  }
278  else
279  {
280  s = s.substr(0, sp);
281  assign_ipv4(s.c_str(), port);
282  }
283  }
284  }
286 }
287 
288 namespace std
289 {
290  template<>
291  struct hash< ::dsn::rpc_address>
292  {
293  size_t operator()(const ::dsn::rpc_address &ep) const
294  {
295  switch (ep.type())
296  {
297  case HOST_TYPE_IPV4:
298  return std::hash<uint32_t>()(ep.ip()) ^ std::hash<uint16_t>()(ep.port());
299  case HOST_TYPE_URI:
300  return std::hash<std::string>()(std::string(ep.to_string()));
301  case HOST_TYPE_GROUP:
302  return std::hash<void*>()(ep.group_address());
303  default:
304  return 0;
305  }
306  }
307  };
308 }
rpc address, which is always encoded into a 64-bit integer
Definition: api_layer1.h:471
4 bytes for IPv4
Definition: api_layer1.h:465
STL namespace.
DSN_API uint32_t dsn_ipv4_local(const char *network_interface)
get local ipv4 according to the given network interface name
struct dsn_address_t::u_t::@2 v4
HOST_TYPE_IPV4
unsigned long long group
dsn_group_t
Definition: api_layer1.h:486
DSN_API const char * dsn_address_to_string(dsn_address_t addr)
dump a RPC address to a meaningful string for logging purpose
reference to an address group object
Definition: api_layer1.h:466
Definition: address.h:110
DSN_API dsn_uri_t dsn_uri_build(const char *url)
build URI address from a string URL, must be destroyed later using dsn_uri_destroy ...
Definition: address.h:52
DSN_API uint32_t dsn_ipv4_from_host(const char *name)
translate from hostname to ipv4 in host machine order
universal resource identifier as a string
Definition: api_layer1.h:467
dsn_host_type_t
rpc address host type
Definition: api_layer1.h:462
Definition: address.h:61