Chromium Code Reviews| 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 |
| (...skipping 53 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 64 // A single asynchronous DNS exchange over UDP, which consists of sending out a | 64 // 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 | 65 // 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. | 66 // matches. Logging is done in the socket and in the outer DnsTransaction. |
| 67 class DnsUDPAttempt { | 67 class DnsUDPAttempt { |
| 68 public: | 68 public: |
| 69 DnsUDPAttempt(scoped_ptr<DatagramClientSocket> socket, | 69 DnsUDPAttempt(scoped_ptr<DatagramClientSocket> socket, |
| 70 const IPEndPoint& server, | 70 const IPEndPoint& server, |
| 71 scoped_ptr<DnsQuery> query, | 71 scoped_ptr<DnsQuery> query, |
| 72 const CompletionCallback& callback) | 72 const CompletionCallback& callback) |
| 73 : next_state_(STATE_NONE), | 73 : next_state_(STATE_NONE), |
| 74 received_malformed_response_(false), | |
| 74 socket_(socket.Pass()), | 75 socket_(socket.Pass()), |
| 75 server_(server), | 76 server_(server), |
| 76 query_(query.Pass()), | 77 query_(query.Pass()), |
| 77 callback_(callback) { | 78 callback_(callback) { |
| 78 } | 79 } |
| 79 | 80 |
| 80 // Starts the attempt. Returns ERR_IO_PENDING if cannot complete synchronously | 81 // Starts the attempt. Returns ERR_IO_PENDING if cannot complete synchronously |
| 81 // and calls |callback| upon completion. | 82 // and calls |callback| upon completion. |
| 82 int Start() { | 83 int Start() { |
| 83 DCHECK_EQ(STATE_NONE, next_state_); | 84 DCHECK_EQ(STATE_NONE, next_state_); |
| (...skipping 59 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 143 rv = DoReadResponse(); | 144 rv = DoReadResponse(); |
| 144 break; | 145 break; |
| 145 case STATE_READ_RESPONSE_COMPLETE: | 146 case STATE_READ_RESPONSE_COMPLETE: |
| 146 rv = DoReadResponseComplete(rv); | 147 rv = DoReadResponseComplete(rv); |
| 147 break; | 148 break; |
| 148 default: | 149 default: |
| 149 NOTREACHED(); | 150 NOTREACHED(); |
| 150 break; | 151 break; |
| 151 } | 152 } |
| 152 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); | 153 } while (rv != ERR_IO_PENDING && next_state_ != STATE_NONE); |
| 153 | 154 return received_malformed_response_ ? ERR_DNS_MALFORMED_RESPONSE : rv; |
|
mmenke
2012/08/28 14:15:54
Err...How does this work? It looks like if we eve
szym
2012/08/28 14:59:44
You're right. This isn't finished yet, and the tes
| |
| 154 return rv; | |
| 155 } | 155 } |
| 156 | 156 |
| 157 int DoConnect() { | 157 int DoConnect() { |
| 158 next_state_ = STATE_SEND_QUERY; | 158 next_state_ = STATE_SEND_QUERY; |
| 159 return socket_->Connect(server_); | 159 return socket_->Connect(server_); |
| 160 } | 160 } |
| 161 | 161 |
| 162 int DoSendQuery() { | 162 int DoSendQuery() { |
| 163 next_state_ = STATE_SEND_QUERY_COMPLETE; | 163 next_state_ = STATE_SEND_QUERY_COMPLETE; |
| 164 return socket_->Write(query_->io_buffer(), | 164 return socket_->Write(query_->io_buffer(), |
| (...skipping 24 matching lines...) Expand all Loading... | |
| 189 base::Unretained(this))); | 189 base::Unretained(this))); |
| 190 } | 190 } |
| 191 | 191 |
| 192 int DoReadResponseComplete(int rv) { | 192 int DoReadResponseComplete(int rv) { |
| 193 DCHECK_NE(ERR_IO_PENDING, rv); | 193 DCHECK_NE(ERR_IO_PENDING, rv); |
| 194 if (rv < 0) | 194 if (rv < 0) |
| 195 return rv; | 195 return rv; |
| 196 | 196 |
| 197 DCHECK(rv); | 197 DCHECK(rv); |
| 198 if (!response_->InitParse(rv, *query_)) { | 198 if (!response_->InitParse(rv, *query_)) { |
| 199 // TODO(szym): Consider making this reaction less aggressive. | |
| 200 // Other implementations simply ignore mismatched responses. Since each | 199 // Other implementations simply ignore mismatched responses. Since each |
| 201 // DnsUDPAttempt binds to a different port, we might find that responses | 200 // DnsUDPAttempt binds to a different port, we might find that responses |
| 202 // to previously timed out queries lead to failures in the future. | 201 // to previously timed out queries lead to failures in the future. |
| 203 // http://crbug.com/107413 | 202 // Our solution is to make another attempt, in case the query truly |
| 204 return ERR_DNS_MALFORMED_RESPONSE; | 203 // failed, but keep this attempt alive, in case it was a false alarm. |
| 204 received_malformed_response_ = true; | |
| 205 next_state_ = STATE_READ_RESPONSE; | |
| 206 return ERR_IO_PENDING; | |
| 205 } | 207 } |
| 206 if (response_->flags() & dns_protocol::kFlagTC) | 208 if (response_->flags() & dns_protocol::kFlagTC) |
| 207 return ERR_DNS_SERVER_REQUIRES_TCP; | 209 return ERR_DNS_SERVER_REQUIRES_TCP; |
| 208 // TODO(szym): Extract TTL for NXDOMAIN results. http://crbug.com/115051 | 210 // TODO(szym): Extract TTL for NXDOMAIN results. http://crbug.com/115051 |
| 209 if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN) | 211 if (response_->rcode() == dns_protocol::kRcodeNXDOMAIN) |
| 210 return ERR_NAME_NOT_RESOLVED; | 212 return ERR_NAME_NOT_RESOLVED; |
| 211 if (response_->rcode() != dns_protocol::kRcodeNOERROR) | 213 if (response_->rcode() != dns_protocol::kRcodeNOERROR) |
| 212 return ERR_DNS_SERVER_FAILED; | 214 return ERR_DNS_SERVER_FAILED; |
| 213 | 215 |
| 214 CHECK(response()); | 216 CHECK(response()); |
| 215 return OK; | 217 return OK; |
| 216 } | 218 } |
| 217 | 219 |
| 218 void OnIOComplete(int rv) { | 220 void OnIOComplete(int rv) { |
| 219 rv = DoLoop(rv); | 221 rv = DoLoop(rv); |
| 220 if (rv != ERR_IO_PENDING) | 222 if (rv != ERR_IO_PENDING) |
| 221 callback_.Run(rv); | 223 callback_.Run(rv); |
| 222 } | 224 } |
| 223 | 225 |
| 224 State next_state_; | 226 State next_state_; |
| 227 bool received_malformed_response_; | |
| 225 | 228 |
| 226 scoped_ptr<DatagramClientSocket> socket_; | 229 scoped_ptr<DatagramClientSocket> socket_; |
| 227 IPEndPoint server_; | 230 IPEndPoint server_; |
| 228 scoped_ptr<DnsQuery> query_; | 231 scoped_ptr<DnsQuery> query_; |
| 229 | 232 |
| 230 scoped_ptr<DnsResponse> response_; | 233 scoped_ptr<DnsResponse> response_; |
| 231 | 234 |
| 232 CompletionCallback callback_; | 235 CompletionCallback callback_; |
| 233 | 236 |
| 234 DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt); | 237 DISALLOW_COPY_AND_ASSIGN(DnsUDPAttempt); |
| (...skipping 344 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 579 } // namespace | 582 } // namespace |
| 580 | 583 |
| 581 // static | 584 // static |
| 582 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( | 585 scoped_ptr<DnsTransactionFactory> DnsTransactionFactory::CreateFactory( |
| 583 DnsSession* session) { | 586 DnsSession* session) { |
| 584 return scoped_ptr<DnsTransactionFactory>( | 587 return scoped_ptr<DnsTransactionFactory>( |
| 585 new DnsTransactionFactoryImpl(session)); | 588 new DnsTransactionFactoryImpl(session)); |
| 586 } | 589 } |
| 587 | 590 |
| 588 } // namespace net | 591 } // namespace net |
| OLD | NEW |