LogCabin
|
00001 /* Copyright (c) 2012 Stanford University 00002 * Copyright (c) 2014 Diego Ongaro 00003 * 00004 * Permission to use, copy, modify, and distribute this software for any 00005 * purpose with or without fee is hereby granted, provided that the above 00006 * copyright notice and this permission notice appear in all copies. 00007 * 00008 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR(S) DISCLAIM ALL WARRANTIES 00009 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 00010 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL AUTHORS BE LIABLE FOR 00011 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 00012 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 00013 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 00014 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 00015 */ 00016 00017 #ifndef LOGCABIN_RPC_ADDRESS_H 00018 #define LOGCABIN_RPC_ADDRESS_H 00019 00020 #include <sys/socket.h> 00021 #include <string> 00022 #include <vector> 00023 00024 #include "Core/Time.h" 00025 00026 namespace LogCabin { 00027 namespace RPC { 00028 00029 /** 00030 * This class resolves user-friendly addresses for services into socket-level 00031 * addresses. It supports DNS lookups for addressing hosts by name, and it 00032 * supports multiple (alternative) addresses. 00033 */ 00034 class Address { 00035 public: 00036 /// Clock used for timeouts. 00037 typedef Core::Time::SteadyClock Clock; 00038 /// Type for absolute time values used for timeouts. 00039 typedef Clock::time_point TimePoint; 00040 00041 /** 00042 * Constructor. You will usually need to call #refresh() before using this 00043 * class. 00044 * \param str 00045 * A string representation of the host and, optionally, a port number. 00046 * - hostname:port 00047 * - hostname 00048 * - IPv4Address:port 00049 * - IPv4Address 00050 * - [IPv6Address]:port 00051 * - [IPv6Address] 00052 * Or a comma-delimited list of these to represent multiple hosts. 00053 * \param defaultPort 00054 * The port number to use if none is specified in str. 00055 */ 00056 Address(const std::string& str, uint16_t defaultPort); 00057 00058 /// Default constructor. 00059 Address(); 00060 00061 /// Copy constructor. 00062 Address(const Address& other); 00063 00064 /// Assignment. 00065 Address& operator=(const Address& other); 00066 00067 /** 00068 * Return true if the sockaddr returned by getSockAddr() is valid. 00069 * \return 00070 * True if refresh() has ever succeeded for this host and port. 00071 * False otherwise. 00072 */ 00073 bool isValid() const; 00074 00075 /** 00076 * Return a sockaddr that may be used to connect a socket to this Address. 00077 * \return 00078 * The returned value will never be NULL and it is always safe to read 00079 * the protocol field from it, even if getSockAddrLen() returns 0. 00080 */ 00081 const sockaddr* getSockAddr() const; 00082 00083 /** 00084 * Return the length in bytes of the sockaddr in getSockAddr(). 00085 * This is the value you'll want to pass in to connect() or bind(). 00086 */ 00087 socklen_t getSockAddrLen() const; 00088 00089 /** 00090 * Return a string describing the sockaddr within this Address. 00091 * This string will reflect the numeric address produced by the latest 00092 * successful call to refresh(), or "Unspecified". 00093 */ 00094 std::string getResolvedString() const; 00095 00096 /** 00097 * Return a string describing this Address. 00098 * This will contain both the user-provided string passed into the 00099 * constructor and the numeric address produced by the latest successful 00100 * call to refresh(). It's the best representation to use in error messages 00101 * for the user. 00102 */ 00103 std::string toString() const; 00104 00105 /** 00106 * Convert (a random one of) the host(s) and port(s) to a sockaddr. 00107 * If the host is a name instead of numeric, this will run a DNS query and 00108 * select a random result. If this query fails, any previous sockaddr will 00109 * be left intact. 00110 * \param timeout 00111 * Not yet implemented. 00112 * \warning 00113 * Timeouts have not been implemented. 00114 * See https://github.com/logcabin/logcabin/issues/75 00115 */ 00116 void refresh(TimePoint timeout); 00117 00118 private: 00119 00120 /** 00121 * The host name(s) or numeric address(es) as passed into the constructor. 00122 */ 00123 std::string originalString; 00124 00125 /** 00126 * A list of (host, port) pairs as parsed from originalString. 00127 * - First component: the host name or numeric address as parsed from the 00128 * string passed into the constructor. This has brackets stripped out of 00129 * IPv6 addresses and is in the form needed by getaddrinfo(). 00130 * - Second component: an ASCII representation of the port number to use. 00131 * It is stored in string form because that's sometimes how it comes into 00132 * the constructor and always what refresh() needs to call getaddrinfo(). 00133 */ 00134 std::vector<std::pair<std::string, std::string>> hosts; 00135 00136 /** 00137 * Storage for the sockaddr returned by getSockAddr. 00138 * This is always zeroed out from len to the end. 00139 */ 00140 sockaddr_storage storage; 00141 00142 /** 00143 * The length in bytes of storage that are in use. 00144 * The remaining bytes of storage are always zeroed out. 00145 */ 00146 socklen_t len; 00147 }; 00148 00149 } // namespace LogCabin::RPC 00150 } // namespace LogCabin 00151 00152 #endif /* LOGCABIN_RPC_ADDRESS_H */