| OLD | NEW | 
|    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. |    1 // Copyright (c) 2012 The Chromium Authors. All rights reserved. | 
|    2 // Use of this source code is governed by a BSD-style license that can be |    2 // Use of this source code is governed by a BSD-style license that can be | 
|    3 // found in the LICENSE file. |    3 // found in the LICENSE file. | 
|    4  |    4  | 
|    5 #include "net/dns/dns_transaction.h" |    5 #include "net/dns/dns_transaction.h" | 
|    6  |    6  | 
|    7 #include <deque> |    7 #include <deque> | 
|    8 #include <string> |    8 #include <string> | 
|    9 #include <vector> |    9 #include <vector> | 
|   10  |   10  | 
|   11 #include "base/bind.h" |   11 #include "base/bind.h" | 
|   12 #include "base/memory/ref_counted.h" |   12 #include "base/memory/ref_counted.h" | 
|   13 #include "base/memory/scoped_ptr.h" |   13 #include "base/memory/scoped_ptr.h" | 
|   14 #include "base/memory/scoped_vector.h" |   14 #include "base/memory/scoped_vector.h" | 
|   15 #include "base/memory/weak_ptr.h" |   15 #include "base/memory/weak_ptr.h" | 
|   16 #include "base/message_loop.h" |   16 #include "base/message_loop.h" | 
|   17 #include "base/rand_util.h" |  | 
|   18 #include "base/stl_util.h" |   17 #include "base/stl_util.h" | 
|   19 #include "base/string_piece.h" |   18 #include "base/string_piece.h" | 
|   20 #include "base/threading/non_thread_safe.h" |   19 #include "base/threading/non_thread_safe.h" | 
|   21 #include "base/timer.h" |   20 #include "base/timer.h" | 
|   22 #include "base/values.h" |   21 #include "base/values.h" | 
|   23 #include "net/base/completion_callback.h" |   22 #include "net/base/completion_callback.h" | 
|   24 #include "net/base/dns_util.h" |   23 #include "net/base/dns_util.h" | 
|   25 #include "net/base/io_buffer.h" |   24 #include "net/base/io_buffer.h" | 
|   26 #include "net/base/ip_endpoint.h" |   25 #include "net/base/ip_endpoint.h" | 
|   27 #include "net/base/net_errors.h" |   26 #include "net/base/net_errors.h" | 
|   28 #include "net/base/net_log.h" |   27 #include "net/base/net_log.h" | 
|   29 #include "net/dns/dns_protocol.h" |   28 #include "net/dns/dns_protocol.h" | 
|   30 #include "net/dns/dns_query.h" |   29 #include "net/dns/dns_query.h" | 
|   31 #include "net/dns/dns_response.h" |   30 #include "net/dns/dns_response.h" | 
|   32 #include "net/dns/dns_session.h" |   31 #include "net/dns/dns_session.h" | 
|   33 #include "net/socket/client_socket_factory.h" |  | 
|   34 #include "net/udp/datagram_client_socket.h" |   32 #include "net/udp/datagram_client_socket.h" | 
|   35  |   33  | 
|   36 namespace net { |   34 namespace net { | 
|   37  |   35  | 
|   38 namespace { |   36 namespace { | 
|   39  |   37  | 
|   40 // Count labels in the fully-qualified name in DNS format. |   38 // Count labels in the fully-qualified name in DNS format. | 
|   41 int CountLabels(const std::string& name) { |   39 int CountLabels(const std::string& name) { | 
|   42   size_t count = 0; |   40   size_t count = 0; | 
|   43   for (size_t i = 0; i < name.size() && name[i]; i += name[i] + 1) |   41   for (size_t i = 0; i < name.size() && name[i]; i += name[i] + 1) | 
| (...skipping 15 matching lines...) Expand all  Loading... | 
|   59   return dict; |   57   return dict; | 
|   60 }; |   58 }; | 
|   61  |   59  | 
|   62 // ---------------------------------------------------------------------------- |   60 // ---------------------------------------------------------------------------- | 
|   63  |   61  | 
|   64 // A single asynchronous DNS exchange over UDP, which consists of sending out a |   62 // A single asynchronous DNS exchange over UDP, which consists of sending out a | 
|   65 // DNS query, waiting for a response, and returning the response that it |   63 // DNS query, waiting for a response, and returning the response that it | 
|   66 // matches. Logging is done in the socket and in the outer DnsTransaction. |   64 // matches. Logging is done in the socket and in the outer DnsTransaction. | 
|   67 class DnsUDPAttempt { |   65 class DnsUDPAttempt { | 
|   68  public: |   66  public: | 
|   69   DnsUDPAttempt(scoped_ptr<DatagramClientSocket> socket, |   67   DnsUDPAttempt(scoped_ptr<DnsSession::SocketLease> socket_lease, | 
|   70                 const IPEndPoint& server, |  | 
|   71                 scoped_ptr<DnsQuery> query, |   68                 scoped_ptr<DnsQuery> query, | 
|   72                 const CompletionCallback& callback) |   69                 const CompletionCallback& callback) | 
|   73       : next_state_(STATE_NONE), |   70       : next_state_(STATE_NONE), | 
|   74         received_malformed_response_(false), |   71         received_malformed_response_(false), | 
|   75         socket_(socket.Pass()), |   72         socket_lease_(socket_lease.Pass()), | 
|   76         server_(server), |  | 
|   77         query_(query.Pass()), |   73         query_(query.Pass()), | 
|   78         callback_(callback) { |   74         callback_(callback) { | 
|   79   } |   75   } | 
|   80  |   76  | 
|   81   // Starts the attempt. Returns ERR_IO_PENDING if cannot complete synchronously |   77   // Starts the attempt. Returns ERR_IO_PENDING if cannot complete synchronously | 
|   82   // and calls |callback| upon completion. |   78   // and calls |callback| upon completion. | 
|   83   int Start() { |   79   int Start() { | 
|   84     DCHECK_EQ(STATE_NONE, next_state_); |   80     DCHECK_EQ(STATE_NONE, next_state_); | 
|   85     next_state_ = STATE_CONNECT; |   81     next_state_ = STATE_SEND_QUERY; | 
|   86     return DoLoop(OK); |   82     return DoLoop(OK); | 
|   87   } |   83   } | 
|   88  |   84  | 
|   89   const DnsQuery* query() const { |   85   const DnsQuery* query() const { | 
|   90     return query_.get(); |   86     return query_.get(); | 
|   91   } |   87   } | 
|   92  |   88  | 
|   93   const DatagramClientSocket* socket() const { |   89   const DatagramClientSocket* socket() const { | 
|   94     return socket_.get(); |   90     return socket_lease_->socket(); | 
|   95   } |   91   } | 
|   96  |   92  | 
|   97   // Returns the response or NULL if has not received a matching response from |   93   // Returns the response or NULL if has not received a matching response from | 
|   98   // the server. |   94   // the server. | 
|   99   const DnsResponse* response() const { |   95   const DnsResponse* response() const { | 
|  100     const DnsResponse* resp = response_.get(); |   96     const DnsResponse* resp = response_.get(); | 
|  101     return (resp != NULL && resp->IsValid()) ? resp : NULL; |   97     return (resp != NULL && resp->IsValid()) ? resp : NULL; | 
|  102   } |   98   } | 
|  103  |   99  | 
|  104   // Returns a Value representing the received response, along with a reference |  100   // Returns a Value representing the received response, along with a reference | 
|  105   // to the NetLog source source of the UDP socket used.  The request must have |  101   // to the NetLog source source of the UDP socket used.  The request must have | 
|  106   // completed before this is called. |  102   // completed before this is called. | 
|  107   Value* NetLogResponseCallback(NetLog::LogLevel /* log_level */) const { |  103   Value* NetLogResponseCallback(NetLog::LogLevel /* log_level */) const { | 
|  108     DCHECK(response_->IsValid()); |  104     DCHECK(response_->IsValid()); | 
|  109  |  105  | 
|  110     DictionaryValue* dict = new DictionaryValue(); |  106     DictionaryValue* dict = new DictionaryValue(); | 
|  111     dict->SetInteger("rcode", response_->rcode()); |  107     dict->SetInteger("rcode", response_->rcode()); | 
|  112     dict->SetInteger("answer_count", response_->answer_count()); |  108     dict->SetInteger("answer_count", response_->answer_count()); | 
|  113     socket_->NetLog().source().AddToEventParameters(dict); |  109     socket()->NetLog().source().AddToEventParameters(dict); | 
|  114     return dict; |  110     return dict; | 
|  115   } |  111   } | 
|  116  |  112  | 
|  117  private: |  113  private: | 
|  118   enum State { |  114   enum State { | 
|  119     STATE_CONNECT, |  | 
|  120     STATE_SEND_QUERY, |  115     STATE_SEND_QUERY, | 
|  121     STATE_SEND_QUERY_COMPLETE, |  116     STATE_SEND_QUERY_COMPLETE, | 
|  122     STATE_READ_RESPONSE, |  117     STATE_READ_RESPONSE, | 
|  123     STATE_READ_RESPONSE_COMPLETE, |  118     STATE_READ_RESPONSE_COMPLETE, | 
|  124     STATE_NONE, |  119     STATE_NONE, | 
|  125   }; |  120   }; | 
|  126  |  121  | 
 |  122   DatagramClientSocket* my_socket() { | 
 |  123     return socket_lease_->socket(); | 
 |  124   } | 
 |  125  | 
|  127   int DoLoop(int result) { |  126   int DoLoop(int result) { | 
|  128     CHECK_NE(STATE_NONE, next_state_); |  127     CHECK_NE(STATE_NONE, next_state_); | 
|  129     int rv = result; |  128     int rv = result; | 
|  130     do { |  129     do { | 
|  131       State state = next_state_; |  130       State state = next_state_; | 
|  132       next_state_ = STATE_NONE; |  131       next_state_ = STATE_NONE; | 
|  133       switch (state) { |  132       switch (state) { | 
|  134         case STATE_CONNECT: |  | 
|  135           rv = DoConnect(); |  | 
|  136           break; |  | 
|  137         case STATE_SEND_QUERY: |  133         case STATE_SEND_QUERY: | 
|  138           rv = DoSendQuery(); |  134           rv = DoSendQuery(); | 
|  139           break; |  135           break; | 
|  140         case STATE_SEND_QUERY_COMPLETE: |  136         case STATE_SEND_QUERY_COMPLETE: | 
|  141           rv = DoSendQueryComplete(rv); |  137           rv = DoSendQueryComplete(rv); | 
|  142           break; |  138           break; | 
|  143         case STATE_READ_RESPONSE: |  139         case STATE_READ_RESPONSE: | 
|  144           rv = DoReadResponse(); |  140           rv = DoReadResponse(); | 
|  145           break; |  141           break; | 
|  146         case STATE_READ_RESPONSE_COMPLETE: |  142         case STATE_READ_RESPONSE_COMPLETE: | 
|  147           rv = DoReadResponseComplete(rv); |  143           rv = DoReadResponseComplete(rv); | 
|  148           break; |  144           break; | 
|  149         default: |  145         default: | 
|  150           NOTREACHED(); |  146           NOTREACHED(); | 
|  151           break; |  147           break; | 
|  152       } |  148       } | 
|  153     } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |  149     } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 
|  154     // If we received a malformed response, and are now waiting for another one, |  150     // If we received a malformed response, and are now waiting for another one, | 
|  155     // indicate to the transaction that the server might be misbehaving. |  151     // indicate to the transaction that the server might be misbehaving. | 
|  156     if (rv == ERR_IO_PENDING && received_malformed_response_) |  152     if (rv == ERR_IO_PENDING && received_malformed_response_) | 
|  157       return ERR_DNS_MALFORMED_RESPONSE; |  153       return ERR_DNS_MALFORMED_RESPONSE; | 
|  158     return rv; |  154     return rv; | 
|  159   } |  155   } | 
|  160  |  156  | 
|  161   int DoConnect() { |  | 
|  162     next_state_ = STATE_SEND_QUERY; |  | 
|  163     return socket_->Connect(server_); |  | 
|  164   } |  | 
|  165  |  | 
|  166   int DoSendQuery() { |  157   int DoSendQuery() { | 
|  167     next_state_ = STATE_SEND_QUERY_COMPLETE; |  158     next_state_ = STATE_SEND_QUERY_COMPLETE; | 
|  168     return socket_->Write(query_->io_buffer(), |  159     return my_socket()->Write(query_->io_buffer(), | 
|  169                           query_->io_buffer()->size(), |  160                               query_->io_buffer()->size(), | 
|  170                           base::Bind(&DnsUDPAttempt::OnIOComplete, |  161                               base::Bind(&DnsUDPAttempt::OnIOComplete, | 
|  171                                      base::Unretained(this))); |  162                                          base::Unretained(this))); | 
|  172   } |  163   } | 
|  173  |  164  | 
|  174   int DoSendQueryComplete(int rv) { |  165   int DoSendQueryComplete(int rv) { | 
|  175     DCHECK_NE(ERR_IO_PENDING, rv); |  166     DCHECK_NE(ERR_IO_PENDING, rv); | 
|  176     if (rv < 0) |  167     if (rv < 0) | 
|  177       return rv; |  168       return rv; | 
|  178  |  169  | 
|  179     // Writing to UDP should not result in a partial datagram. |  170     // Writing to UDP should not result in a partial datagram. | 
|  180     if (rv != query_->io_buffer()->size()) |  171     if (rv != query_->io_buffer()->size()) | 
|  181       return ERR_MSG_TOO_BIG; |  172       return ERR_MSG_TOO_BIG; | 
|  182  |  173  | 
|  183     next_state_ = STATE_READ_RESPONSE; |  174     next_state_ = STATE_READ_RESPONSE; | 
|  184     return OK; |  175     return OK; | 
|  185   } |  176   } | 
|  186  |  177  | 
|  187   int DoReadResponse() { |  178   int DoReadResponse() { | 
|  188     next_state_ = STATE_READ_RESPONSE_COMPLETE; |  179     next_state_ = STATE_READ_RESPONSE_COMPLETE; | 
|  189     response_.reset(new DnsResponse()); |  180     response_.reset(new DnsResponse()); | 
|  190     return socket_->Read(response_->io_buffer(), |  181     return my_socket()->Read(response_->io_buffer(), | 
|  191                          response_->io_buffer()->size(), |  182                              response_->io_buffer()->size(), | 
|  192                          base::Bind(&DnsUDPAttempt::OnIOComplete, |  183                              base::Bind(&DnsUDPAttempt::OnIOComplete, | 
|  193                                     base::Unretained(this))); |  184                                         base::Unretained(this))); | 
|  194   } |  185   } | 
|  195  |  186  | 
|  196   int DoReadResponseComplete(int rv) { |  187   int DoReadResponseComplete(int rv) { | 
|  197     DCHECK_NE(ERR_IO_PENDING, rv); |  188     DCHECK_NE(ERR_IO_PENDING, rv); | 
|  198     if (rv < 0) |  189     if (rv < 0) | 
|  199       return rv; |  190       return rv; | 
|  200  |  191  | 
|  201     DCHECK(rv); |  192     DCHECK(rv); | 
|  202     if (!response_->InitParse(rv, *query_)) { |  193     if (!response_->InitParse(rv, *query_)) { | 
|  203       // Other implementations simply ignore mismatched responses. Since each |  194       // Other implementations simply ignore mismatched responses. Since each | 
| (...skipping 19 matching lines...) Expand all  Loading... | 
|  223  |  214  | 
|  224   void OnIOComplete(int rv) { |  215   void OnIOComplete(int rv) { | 
|  225     rv = DoLoop(rv); |  216     rv = DoLoop(rv); | 
|  226     if (rv != ERR_IO_PENDING) |  217     if (rv != ERR_IO_PENDING) | 
|  227       callback_.Run(rv); |  218       callback_.Run(rv); | 
|  228   } |  219   } | 
|  229  |  220  | 
|  230   State next_state_; |  221   State next_state_; | 
|  231   bool received_malformed_response_; |  222   bool received_malformed_response_; | 
|  232  |  223  | 
|  233   scoped_ptr<DatagramClientSocket> socket_; |  224   scoped_ptr<DnsSession::SocketLease> socket_lease_; | 
|  234   IPEndPoint server_; |  | 
|  235   scoped_ptr<DnsQuery> query_; |  225   scoped_ptr<DnsQuery> query_; | 
|  236  |  226  | 
|  237   scoped_ptr<DnsResponse> response_; |  227   scoped_ptr<DnsResponse> response_; | 
|  238  |  228  | 
|  239   CompletionCallback callback_; |  229   CompletionCallback callback_; | 
|  240  |  230  | 
|  241   DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt); |  231   DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt); | 
|  242 }; |  232 }; | 
|  243  |  233  | 
|  244 // ---------------------------------------------------------------------------- |  234 // ---------------------------------------------------------------------------- | 
| (...skipping 139 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  384  |  374  | 
|  385     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, result.rv); |  375     net_log_.EndEventWithNetErrorCode(NetLog::TYPE_DNS_TRANSACTION, result.rv); | 
|  386     callback.Run(this, result.rv, response); |  376     callback.Run(this, result.rv, response); | 
|  387   } |  377   } | 
|  388  |  378  | 
|  389   // Makes another attempt at the current name, |qnames_.front()|, using the |  379   // Makes another attempt at the current name, |qnames_.front()|, using the | 
|  390   // next nameserver. |  380   // next nameserver. | 
|  391   AttemptResult MakeAttempt() { |  381   AttemptResult MakeAttempt() { | 
|  392     unsigned attempt_number = attempts_.size(); |  382     unsigned attempt_number = attempts_.size(); | 
|  393  |  383  | 
|  394 #if defined(OS_WIN) |  | 
|  395     // Avoid the Windows firewall warning about explicit UDP binding. |  | 
|  396     // TODO(szym): Reuse a pool of pre-bound sockets. http://crbug.com/107413 |  | 
|  397     DatagramSocket::BindType bind_type = DatagramSocket::DEFAULT_BIND; |  | 
|  398 #else |  | 
|  399     DatagramSocket::BindType bind_type = DatagramSocket::RANDOM_BIND; |  | 
|  400 #endif |  | 
|  401  |  | 
|  402     scoped_ptr<DatagramClientSocket> socket( |  | 
|  403         session_->socket_factory()->CreateDatagramClientSocket( |  | 
|  404             bind_type, |  | 
|  405             base::Bind(&base::RandInt), |  | 
|  406             net_log_.net_log(), |  | 
|  407             net_log_.source())); |  | 
|  408  |  | 
|  409     uint16 id = session_->NextQueryId(); |  384     uint16 id = session_->NextQueryId(); | 
|  410     scoped_ptr<DnsQuery> query; |  385     scoped_ptr<DnsQuery> query; | 
|  411     if (attempts_.empty()) { |  386     if (attempts_.empty()) { | 
|  412       query.reset(new DnsQuery(id, qnames_.front(), qtype_)); |  387       query.reset(new DnsQuery(id, qnames_.front(), qtype_)); | 
|  413     } else { |  388     } else { | 
|  414       query.reset(attempts_[0]->query()->CloneWithNewId(id)); |  389       query.reset(attempts_[0]->query()->CloneWithNewId(id)); | 
|  415     } |  390     } | 
|  416  |  391  | 
|  417     net_log_.AddEvent(NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, |  | 
|  418                       socket->NetLog().source().ToEventParametersCallback()); |  | 
|  419  |  | 
|  420     const DnsConfig& config = session_->config(); |  392     const DnsConfig& config = session_->config(); | 
|  421  |  393  | 
|  422     unsigned server_index = first_server_index_ + |  394     unsigned server_index = first_server_index_ + | 
|  423         (attempt_number % config.nameservers.size()); |  395         (attempt_number % config.nameservers.size()); | 
|  424  |  396  | 
|  425     DnsUDPAttempt* attempt = new DnsUDPAttempt( |  397     DnsUDPAttempt* attempt = new DnsUDPAttempt( | 
|  426         socket.Pass(), |  398         session_->AllocateSocket(server_index, net_log_.source()), | 
|  427         config.nameservers[server_index], |  | 
|  428         query.Pass(), |  399         query.Pass(), | 
|  429         base::Bind(&DnsTransactionImpl::OnAttemptComplete, |  400         base::Bind(&DnsTransactionImpl::OnAttemptComplete, | 
|  430                    base::Unretained(this), |  401                    base::Unretained(this), | 
|  431                    attempt_number)); |  402                    attempt_number)); | 
|  432  |  403  | 
 |  404     net_log_.AddEvent( | 
 |  405         NetLog::TYPE_DNS_TRANSACTION_ATTEMPT, | 
 |  406         attempt->socket()->NetLog().source().ToEventParametersCallback()); | 
 |  407  | 
|  433     attempts_.push_back(attempt); |  408     attempts_.push_back(attempt); | 
|  434  |  409  | 
|  435     int rv = attempt->Start(); |  410     int rv = attempt->Start(); | 
|  436     if (rv == ERR_IO_PENDING) { |  411     if (rv == ERR_IO_PENDING) { | 
|  437       timer_.Stop(); |  412       timer_.Stop(); | 
|  438       base::TimeDelta timeout = session_->NextTimeout(attempt_number); |  413       base::TimeDelta timeout = session_->NextTimeout(attempt_number); | 
|  439       timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout); |  414       timer_.Start(FROM_HERE, timeout, this, &DnsTransactionImpl::OnTimeout); | 
|  440     } |  415     } | 
|  441     return AttemptResult(rv, attempt); |  416     return AttemptResult(rv, attempt); | 
|  442   } |  417   } | 
| (...skipping 146 matching lines...) Expand 10 before | Expand all | Expand 10 after  Loading... | 
|  589 }  // namespace |  564 }  // namespace | 
|  590  |  565  | 
|  591 // static |  566 // static | 
|  592 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( |  567 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( | 
|  593     DnsSession* session) { |  568     DnsSession* session) { | 
|  594   return scoped_ptr<DnsTransactionFactory>( |  569   return scoped_ptr<DnsTransactionFactory>( | 
|  595       new DnsTransactionFactoryImpl(session)); |  570       new DnsTransactionFactoryImpl(session)); | 
|  596 } |  571 } | 
|  597  |  572  | 
|  598 }  // namespace net |  573 }  // namespace net | 
| OLD | NEW |