1 #include "HostLookup.hxx"
4 #include <sys/socket.h>
9 #include <simgear/threads/SGThread.hxx>
16 class Resolver : public SGThread
21 // take lock when resolver starts,
22 // won't release until it's actually running, and waiting on the
23 // condition. Otherwise we get a race when starting.
30 _cond.wait(_lock); // wait until there's something to lookup
32 // find the first un-resolved entry in the cache
33 HostCache::iterator it;
34 for (it = _cache.begin(); it != _cache.end(); ++it) {
35 if (!it->second->resolved()) {
40 if (it == _cache.end()) {
44 string host = it->first;
45 // don't hold any locks while looking up
48 // start the actual lookup - may take a long period of time!
49 // (eg, one, five or sixty seconds)
50 struct addrinfo hints;
51 bzero(&hints, sizeof(struct addrinfo));
52 hints.ai_family = PF_UNSPEC;
54 struct addrinfo *results;
56 int result = getaddrinfo(host.c_str(), NULL, &hints, &results);
57 _lock.lock(); // take the lock back before going any further
60 _cache[host]->resolve(IPAddress(results->ai_addr, results->ai_addrlen));
61 freeaddrinfo(results);
62 } else if (result == EAGAIN) {
65 const char* errMsg = gai_strerror(result);
66 // bad lookup, remove from cache? or set as failed?
74 void addLookup(HostLookup* l)
77 _cache[l->host()] = l;
82 HostLookup* lookup(const string& host)
85 HostCache::iterator it = _cache.find(host);
86 HostLookup* result = it->second;
94 typedef std::map<string, HostLookup*> HostCache;
98 Resolver* static_resolve = NULL;
100 HostLookup* HostLookup::lookup(const string& host)
102 if (!static_resolve) {
103 static_resolve = new Resolver;
104 static_resolve->start();
107 HostLookup* l = static_resolve->lookup(host);
112 l = new HostLookup(host);
113 SGReferenced::get(l);
114 static_resolve->addLookup(l);
118 HostLookup::HostLookup(const std::string& h) :
124 void HostLookup::resolve(const IPAddress& addr)
132 void HostLookup::fail()