RTBKit  0.9
Open-source framework to create real-time ad bidding systems.
soa/service/named_endpoint.cc
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
 All Classes Namespaces Functions Variables Typedefs Enumerations Enumerator