Chromium Code Reviews| Index: chrome/browser/sync/notifier/base/async_dns_lookup.cc |
| =================================================================== |
| --- chrome/browser/sync/notifier/base/async_dns_lookup.cc (revision 0) |
| +++ chrome/browser/sync/notifier/base/async_dns_lookup.cc (revision 0) |
| @@ -0,0 +1,133 @@ |
| +// Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| +// Use of this source code is governed by a BSD-style license that can be |
| +// found in the LICENSE file. |
| + |
| +#include "chrome/browser/sync/notifier/base/async_dns_lookup.h" |
| + |
| +#ifdef POSIX |
| +#include <arpa/inet.h> |
| +#include <netinet/in.h> |
| +#include <netinet/ip.h> |
| +#include <netdb.h> |
| +#include <sys/socket.h> |
| +#include <sys/types.h> |
| +#endif // POSIX |
| + |
| +#include <vector> |
| + |
| +#include "chrome/browser/sync/notifier/base/nethelpers.h" |
| +#include "chrome/browser/sync/notifier/gaia_auth/inet_aton.h" |
| +#include "talk/base/byteorder.h" |
| +#include "talk/base/common.h" |
| +#include "talk/base/logging.h" |
| +#include "talk/base/socketaddress.h" |
| +#include "talk/base/thread.h" |
| + |
| +enum { MSG_TIMEOUT = talk_base::SignalThread::ST_MSG_FIRST_AVAILABLE }; |
| + |
| +#ifndef WIN32 |
| +const int WSAHOST_NOT_FOUND = 11001; // follows the format in winsock2.h |
| +#endif // WIN32 |
| + |
| +namespace notifier { |
| + |
| +AsyncDNSLookup::AsyncDNSLookup(const talk_base::SocketAddress& server) |
| + : server_(new talk_base::SocketAddress(server)), |
| + error_(0) { |
| + // Timeout after 5 seconds. |
| + talk_base::Thread::Current()->PostDelayed(5000, this, MSG_TIMEOUT); |
| +} |
| + |
| +AsyncDNSLookup::~AsyncDNSLookup() { |
| +} |
| + |
| +void AsyncDNSLookup::DoWork() { |
| + std::string hostname(server_->IPAsString()); |
| + |
| + in_addr addr; |
| + if (inet_aton(hostname.c_str(), &addr)) { |
| + talk_base::CritScope scope(&cs_); |
| + ip_list_.push_back(talk_base::NetworkToHost32(addr.s_addr)); |
| + } else { |
| + LOG_F(LS_VERBOSE) << "(" << hostname << ")"; |
| + hostent ent; |
| + char buffer[8192]; |
| + int errcode = 0; |
| + hostent* host = SafeGetHostByName(hostname.c_str(), &ent, |
| + buffer, sizeof(buffer), |
| + &errcode); |
| + talk_base::Thread::Current()->Clear(this, MSG_TIMEOUT); |
| + if (host) { |
| + talk_base::CritScope scope(&cs_); |
| + |
| + // Check to see if this already timed out. |
| + if (error_ == 0) { |
| + for (int index = 0; true; ++index) { |
| + uint32* addr = reinterpret_cast<uint32*>(host->h_addr_list[index]); |
| + if (addr == 0) { // 0 = end of list |
| + break; |
| + } |
| + uint32 ip = talk_base::NetworkToHost32(*addr); |
| + LOG_F(LS_VERBOSE) << "(" << hostname << ") resolved to: " |
| + << talk_base::SocketAddress::IPToString(ip); |
| + ip_list_.push_back(ip); |
| + } |
| + // Maintain the invariant that either the list is not empty |
| + // or the error is non zero when we are done with processing |
| + // the dnslookup. |
| + if (ip_list_.empty() && error_ == 0) { |
| + error_ = WSAHOST_NOT_FOUND; |
| + } |
| + } |
| + FreeHostEnt(host); |
| + } else { |
| + { // Scoping for the critical section. |
| + talk_base::CritScope scope(&cs_); |
| + |
| + // Check to see if this already timed out. |
| + if (error_ == 0) { |
| + error_ = errcode; |
| + } |
| + } |
| + LOG_F(LS_ERROR) << "(" << hostname << ") error: " << error_; |
| + } |
| + } |
| +} |
| + |
| +void AsyncDNSLookup::OnMessage(talk_base::Message* message) { |
| + ASSERT(message); |
| + if (message->message_id == MSG_TIMEOUT) { |
| + OnTimeout(); |
| + } else { |
| + talk_base::SignalThread::OnMessage(message); |
| + } |
| +} |
| + |
| +void AsyncDNSLookup::OnTimeout() { |
| + // Allow the scope for the critical section to be the whole |
| + // method, just to be sure that the worker thread can't exit |
| + // while we are doing SignalWorkDone (because that could possibly |
| + // cause the class to be deleted). |
| + talk_base::CritScope scope(&cs_); |
| + |
| + // Check to see if the ip list was already filled (or errored out). |
| + if (!ip_list_.empty() || error_ != 0) { |
| + return; |
| + } |
| + |
| + // Worker thread is taking too long so timeout. |
| + error_ = WSAHOST_NOT_FOUND; |
| + |
| + // Rely on the caller to do the Release/Destroy. |
| + // |
| + // Doing this signal while holding cs_ won't cause a deadlock because |
| + // the AsyncDNSLookup::DoWork thread doesn't have any locks at this point, |
| + // and it is the only thread being held up by this. |
| + SignalWorkDone(this); |
| + |
| + // Ensure that no more "WorkDone" signaling is done. |
| + // Don't call Release or Destroy since that was already done |
| + // by the callback. |
| + SignalWorkDone.disconnect_all(); |
| +} |
|
idana
2009/09/10 05:44:37
Add blank line.
|
| +} // namespace notifier |
| Property changes on: chrome\browser\sync\notifier\base\async_dns_lookup.cc |
| ___________________________________________________________________ |
| Added: svn:eol-style |
| + LF |