RTBKit
0.9
Open-source framework to create real-time ad bidding systems.
|
00001 /* named_endpoint.cc 00002 Jeremy Barnes, 24 September 2012 00003 Copyright (c) 2012 Datacratic Inc. All rights reserved. 00004 00005 Endpoint named so that you can connect to it by name (via a discovery 00006 service). 00007 */ 00008 00009 #include "named_endpoint.h" 00010 #include <sys/types.h> 00011 #include <ifaddrs.h> 00012 #include <net/if.h> 00013 #include <arpa/inet.h> 00014 #include <netdb.h> 00015 #include "jml/utils/guard.h" 00016 #include <sys/utsname.h> 00017 00018 using namespace std; 00019 00020 namespace Datacratic { 00021 00022 00023 /*****************************************************************************/ 00024 /* NAMED ENDPOINT */ 00025 /*****************************************************************************/ 00026 00027 void 00028 NamedEndpoint:: 00029 init(std::shared_ptr<ConfigurationService> config, 00030 const std::string & endpointName) 00031 { 00032 this->config = config; 00033 this->endpointName = endpointName; 00034 } 00035 00036 void 00037 NamedEndpoint:: 00038 publishAddress(const std::string & address, 00039 const Json::Value & addressConfig) 00040 { 00041 ExcAssert(config); 00042 00043 //cerr << "publishing " << address << " with " << addressConfig << endl; 00044 config->setUnique(endpointName + "/" + address, 00045 addressConfig); 00046 00047 for (auto & address: addressConfig) { 00048 if (address.isMember("transports")) { 00049 for (auto & transport: address["transports"]) { 00050 if (transport.isMember("uri")) { 00051 publishedUris.emplace_back(transport["uri"].asString()); 00052 } 00053 } 00054 } 00055 } 00056 } 00057 00058 vector<string> 00059 NamedEndpoint:: 00060 getPublishedUris() 00061 const 00062 { 00063 return publishedUris; 00064 } 00065 00066 std::string 00067 NamedEndpoint:: 00068 addrToString(const sockaddr * addr) 00069 { 00070 switch (addr->sa_family) { 00071 case AF_INET: 00072 case AF_INET6: { 00073 char host[NI_MAXHOST]; 00074 int s = getnameinfo(addr, 00075 (addr->sa_family == AF_INET) 00076 ? sizeof(struct sockaddr_in) 00077 : sizeof(struct sockaddr_in6), 00078 host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); 00079 if (s != 0) 00080 throw ML::Exception("getnameinfo: %s", 00081 gai_strerror(s)); 00082 return host; 00083 } 00084 default: 00085 return ""; 00086 } 00087 } 00088 00089 std::string 00090 NamedEndpoint:: 00091 addrToIp(const std::string & addr) 00092 { 00093 addrinfo * info = 0; 00094 addrinfo hints = { 0, AF_INET, SOCK_STREAM, 0, 0, 0, 0, 0 }; 00095 int res = getaddrinfo(addr.c_str(), 0, &hints, &info); 00096 if (res != 0) 00097 throw ML::Exception("addrToIp(%s): %s", addr.c_str(), 00098 gai_strerror(res)); 00099 if (info == 0) 00100 throw ML::Exception("no addresses"); 00101 ML::Call_Guard guard([&] () { freeaddrinfo(info); }); 00102 00103 // Now we have it as a sockaddr_t. Convert it back to a numeric 00104 // address 00105 return addrToString(info->ai_addr); 00106 } 00107 00108 std::vector<NamedEndpoint::Interface> 00109 NamedEndpoint:: 00110 getInterfaces(const std::set<int> & families, 00111 int flagsRequired, 00112 int flagsExcluded) 00113 { 00114 using namespace std; 00115 00116 ifaddrs * addrs = 0; 00117 00118 int res = getifaddrs(&addrs); 00119 if (res != 0) 00120 throw ML::Exception(errno, "getifaddrs failed"); 00121 ML::Call_Guard guard([&] () { freeifaddrs(addrs); }); 00122 00123 vector<Interface> result; 00124 00125 for (ifaddrs * p = addrs; p; p = p->ifa_next) { 00126 00127 if (!p->ifa_addr) 00128 continue; 00129 if (!families.count(p->ifa_addr->sa_family)) 00130 continue; 00131 if ((p->ifa_flags & flagsRequired) != flagsRequired) 00132 continue; 00133 if ((p->ifa_flags & flagsExcluded) != 0) 00134 continue; 00135 00136 Interface iface; 00137 iface.family = p->ifa_addr->sa_family; 00138 iface.name = p->ifa_name; 00139 iface.addr = addrToString(p->ifa_addr); 00140 iface.netmask = addrToString(p->ifa_netmask); 00141 iface.broadcast = addrToString(p->ifa_broadaddr); 00142 iface.flags = p->ifa_flags; 00143 00144 iface.up = p->ifa_flags & IFF_UP; 00145 iface.running = p->ifa_flags & IFF_RUNNING; 00146 iface.loopback = p->ifa_flags & IFF_LOOPBACK; 00147 iface.pointtopoint = p->ifa_flags & IFF_POINTOPOINT; 00148 iface.noarp = p->ifa_flags & IFF_NOARP; 00149 00150 // TODO: better way of detecting non-routable addresses 00151 if (iface.loopback || iface.addr == "127.0.0.1") { 00152 utsname name; 00153 if (uname(&name)) 00154 throw ML::Exception(errno, "uname"); 00155 iface.hostScope = name.nodename; 00156 } 00157 else { 00158 iface.hostScope = "*"; 00159 // Other scopes... 00160 } 00161 00162 #if 0 00163 if (iface.loopback) 00164 iface.type = "loopback"; 00165 else if (iface.pointtopoint) 00166 iface.type = "p2p"; 00167 #endif 00168 result.push_back(iface); 00169 } 00170 00171 return result; 00172 } 00173 00174 00175 } // namespace Datacratic