Chromium Code Reviews| OLD | NEW |
|---|---|
| 1 // Copyright (c) 2013 The Chromium Authors. All rights reserved. | 1 // Copyright (c) 2013 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/mdns_client_impl.h" | 5 #include "net/dns/mdns_client_impl.h" |
| 6 | 6 |
| 7 #include "base/bind.h" | 7 #include "base/bind.h" |
| 8 #include "base/message_loop_proxy.h" | 8 #include "base/message_loop_proxy.h" |
| 9 #include "base/stl_util.h" | 9 #include "base/stl_util.h" |
| 10 #include "base/time/default_clock.h" | 10 #include "base/time/default_clock.h" |
| 11 #include "net/base/dns_util.h" | 11 #include "net/base/dns_util.h" |
| 12 #include "net/base/net_errors.h" | 12 #include "net/base/net_errors.h" |
| 13 #include "net/base/net_log.h" | 13 #include "net/base/net_log.h" |
| 14 #include "net/base/rand_callback.h" | 14 #include "net/base/rand_callback.h" |
| 15 #include "net/dns/dns_protocol.h" | 15 #include "net/dns/dns_protocol.h" |
| 16 #include "net/dns/mdns_query.h" | |
| 17 #include "net/udp/datagram_socket.h" | 16 #include "net/udp/datagram_socket.h" |
| 18 | 17 |
| 19 namespace net { | 18 namespace net { |
| 20 | 19 |
| 21 static const char kMDNSMulticastGroupIPv4[] = "224.0.0.251"; | 20 static const char kMDnsMulticastGroupIPv4[] = "224.0.0.251"; |
| 22 static const char kMDNSMulticastGroupIPv6[] = "FF02::FB"; | 21 static const char kMDnsMulticastGroupIPv6[] = "FF02::FB"; |
| 23 | 22 |
| 24 static const unsigned kMDnsTransactionTimeoutSeconds = 3; | 23 static const unsigned kMDnsTransactionNoResultsSeconds = 3; |
| 25 | 24 |
| 26 MDnsClientImpl::Core::Core(MDnsClientImpl* client, | 25 MDnsClientImpl::Core::Core(MDnsClientImpl* client, |
| 27 MDnsConnectionFactory* connection_factory) | 26 MDnsConnectionFactory* connection_factory) |
| 28 : client_(client), connection_(connection_factory->CreateConnection(this)) { | 27 : client_(client), connection_(connection_factory->CreateConnection(this)) { |
| 29 } | 28 } |
| 30 | 29 |
| 31 MDnsClientImpl::Core::~Core() { | 30 MDnsClientImpl::Core::~Core() { |
| 32 cleanup_callback_.Cancel(); | 31 cleanup_callback_.Cancel(); |
| 33 STLDeleteValues(&listeners_); | 32 STLDeleteValues(&listeners_); |
| 34 } | 33 } |
| 35 | 34 |
| 36 bool MDnsClientImpl::Core::Init() { | 35 bool MDnsClientImpl::Core::Init() { |
| 37 return connection_->Init(); | 36 return connection_->Init() == OK; |
| 38 } | 37 } |
| 39 | 38 |
| 40 bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) { | 39 bool MDnsClientImpl::Core::SendQuery(uint16 rrtype, std::string name) { |
| 41 std::string name_dns; | 40 std::string name_dns; |
| 42 if (!DNSDomainFromDot(name, &name_dns)) | 41 if (!DNSDomainFromDot(name, &name_dns)) |
| 43 return false; | 42 return false; |
| 44 | 43 |
| 45 MDnsQuery query(name_dns, rrtype); | 44 // TODO(noamsml): Remove RD flag from query and add known-answer suppression. |
| 45 DnsQuery query(0, name_dns, rrtype); | |
| 46 | 46 |
| 47 connection_->Send(query.io_buffer(), query.size()); | 47 return connection_->Send(query.io_buffer(), query.io_buffer()->size()) == OK; |
| 48 | |
| 49 return true; | |
| 50 } | 48 } |
| 51 | 49 |
| 52 void MDnsClientImpl::Core::HandlePacket(DnsResponse* response, | 50 void MDnsClientImpl::Core::HandlePacket(DnsResponse* response, |
| 53 int bytes_read) { | 51 int bytes_read) { |
| 54 unsigned offset; | 52 unsigned offset; |
| 55 | 53 |
| 56 if (!response->InitParseWithoutQuery(bytes_read)) { | 54 if (!response->InitParseWithoutQuery(bytes_read)) { |
| 57 LOG(WARNING) << "Could not understand an mDNS packet."; | 55 LOG(WARNING) << "Could not understand an mDNS packet."; |
| 58 return; // Message is unreadable. | 56 return; // Message is unreadable. |
| 59 } | 57 } |
| (...skipping 54 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 114 } | 112 } |
| 115 | 113 |
| 116 AlertListeners(update_external, | 114 AlertListeners(update_external, |
| 117 ListenerKey(record->type(), record->name()), record); | 115 ListenerKey(record->type(), record->name()), record); |
| 118 // Alert listeners listening only for rrtype and not for name. | 116 // Alert listeners listening only for rrtype and not for name. |
| 119 AlertListeners(update_external, ListenerKey(record->type(), ""), record); | 117 AlertListeners(update_external, ListenerKey(record->type(), ""), record); |
| 120 } | 118 } |
| 121 } | 119 } |
| 122 } | 120 } |
| 123 | 121 |
| 122 void MDnsClientImpl::Core::OnConnectionError(int error) { | |
| 123 // TODO(noamsml): On connection error, recreate connection and flush cache. | |
| 124 } | |
| 125 | |
| 124 void MDnsClientImpl::Core::AlertListeners( | 126 void MDnsClientImpl::Core::AlertListeners( |
| 125 MDnsUpdateType update_type, | 127 MDnsUpdateType update_type, |
| 126 const ListenerKey& key, | 128 const ListenerKey& key, |
| 127 const RecordParsed* record) { | 129 const RecordParsed* record) { |
| 128 ListenerMap::iterator listener_map_iterator = listeners_.find(key); | 130 ListenerMap::iterator listener_map_iterator = listeners_.find(key); |
| 129 if (listener_map_iterator == listeners_.end()) return; | 131 if (listener_map_iterator == listeners_.end()) return; |
| 130 | 132 |
| 131 FOR_EACH_OBSERVER(MDnsListenerImpl, *listener_map_iterator->second, | 133 FOR_EACH_OBSERVER(MDnsListenerImpl, *listener_map_iterator->second, |
| 132 AlertDelegate(update_type, record)); | 134 AlertDelegate(update_type, record)); |
| 133 } | 135 } |
| 134 | 136 |
| 135 void MDnsClientImpl::Core::AddListener( | 137 void MDnsClientImpl::Core::AddListener( |
| 136 MDnsListenerImpl* listener, bool alert_existing_records) { | 138 MDnsListenerImpl* listener) { |
| 137 ListenerKey key(listener->GetType(), listener->GetName()); | 139 ListenerKey key(listener->GetType(), listener->GetName()); |
| 138 std::pair<ListenerMap::iterator, bool> observer_insert_result = | 140 std::pair<ListenerMap::iterator, bool> observer_insert_result = |
| 139 listeners_.insert( | 141 listeners_.insert( |
| 140 make_pair(key, static_cast<ObserverList<MDnsListenerImpl>*>(NULL))); | 142 make_pair(key, static_cast<ObserverList<MDnsListenerImpl>*>(NULL))); |
| 141 | 143 |
| 142 // If an equivalent key does not exist, actually create the observer list. | 144 // If an equivalent key does not exist, actually create the observer list. |
| 143 if (observer_insert_result.second) { | 145 if (observer_insert_result.second) { |
| 144 observer_insert_result.first->second = new ObserverList<MDnsListenerImpl>(); | 146 observer_insert_result.first->second = new ObserverList<MDnsListenerImpl>(); |
| 145 } | 147 } |
| 146 | 148 |
| 147 ObserverList<MDnsListenerImpl>* observer_list = | 149 ObserverList<MDnsListenerImpl>* observer_list = |
| 148 observer_insert_result.first->second; | 150 observer_insert_result.first->second; |
| 149 | 151 |
| 150 observer_list->AddObserver(listener); | 152 observer_list->AddObserver(listener); |
| 151 | |
| 152 if (alert_existing_records) { | |
| 153 std::vector<const RecordParsed*> records; | |
| 154 | |
| 155 cache_.FindDnsRecords(listener->GetType(), listener->GetName(), | |
| 156 &records, base::Time::Now()); | |
| 157 | |
| 158 base::WeakPtr<MDnsListenerImpl> weak_listener = listener->AsWeakPtr(); | |
| 159 | |
| 160 for (std::vector<const RecordParsed*>::iterator i = records.begin(); | |
| 161 i != records.end(); i++) { | |
| 162 if (weak_listener) { | |
| 163 weak_listener->AlertDelegate(kMDnsRecordAdded, *i); | |
| 164 } | |
| 165 } | |
| 166 } | |
| 167 } | 153 } |
| 168 | 154 |
| 169 void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) { | 155 void MDnsClientImpl::Core::RemoveListener(MDnsListenerImpl* listener) { |
| 170 ListenerKey key(listener->GetType(), listener->GetName()); | 156 ListenerKey key(listener->GetType(), listener->GetName()); |
| 171 ListenerMap::iterator observer_list_iterator = listeners_.find(key); | 157 ListenerMap::iterator observer_list_iterator = listeners_.find(key); |
| 172 | 158 |
| 173 DCHECK(observer_list_iterator != listeners_.end()); | 159 DCHECK(observer_list_iterator != listeners_.end()); |
| 174 DCHECK(observer_list_iterator->second->HasObserver(listener)); | 160 DCHECK(observer_list_iterator->second->HasObserver(listener)); |
| 175 | 161 |
| 176 observer_list_iterator->second->RemoveObserver(listener); | 162 observer_list_iterator->second->RemoveObserver(listener); |
| (...skipping 85 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
| 262 } | 248 } |
| 263 } | 249 } |
| 264 | 250 |
| 265 bool MDnsClientImpl::IsListeningForTests() { | 251 bool MDnsClientImpl::IsListeningForTests() { |
| 266 return core_.get() != NULL; | 252 return core_.get() != NULL; |
| 267 } | 253 } |
| 268 | 254 |
| 269 scoped_ptr<MDnsListener> MDnsClientImpl::CreateListener( | 255 scoped_ptr<MDnsListener> MDnsClientImpl::CreateListener( |
| 270 uint16 rrtype, | 256 uint16 rrtype, |
| 271 const std::string& name, | 257 const std::string& name, |
| 272 bool active, | |
| 273 bool alert_existing_records, | |
| 274 MDnsListener::Delegate* delegate) { | 258 MDnsListener::Delegate* delegate) { |
| 275 return scoped_ptr<net::MDnsListener>( | 259 return scoped_ptr<net::MDnsListener>( |
| 276 new MDnsListenerImpl(rrtype, name, active, alert_existing_records, | 260 new MDnsListenerImpl(rrtype, name, delegate, this)); |
| 277 delegate, this)); | |
| 278 } | 261 } |
| 279 | 262 |
| 280 scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction( | 263 scoped_ptr<MDnsTransaction> MDnsClientImpl::CreateTransaction( |
| 281 uint16 rrtype, | 264 uint16 rrtype, |
| 282 const std::string& name, | 265 const std::string& name, |
| 266 int flags, | |
| 283 const MDnsTransaction::ResultCallback& callback) { | 267 const MDnsTransaction::ResultCallback& callback) { |
| 284 return scoped_ptr<MDnsTransaction>( | 268 return scoped_ptr<MDnsTransaction>( |
| 285 new MDnsTransactionImpl(rrtype, name, callback, this)); | 269 new MDnsTransactionImpl(rrtype, name, flags, callback, this)); |
| 286 } | 270 } |
| 287 | 271 |
| 288 MDnsListenerImpl::MDnsListenerImpl( | 272 MDnsListenerImpl::MDnsListenerImpl( |
| 289 uint16 rrtype, | 273 uint16 rrtype, |
| 290 const std::string& name, | 274 const std::string& name, |
| 291 bool active, | |
| 292 bool alert_existing_records, | |
| 293 MDnsListener::Delegate* delegate, | 275 MDnsListener::Delegate* delegate, |
| 294 MDnsClientImpl* client) | 276 MDnsClientImpl* client) |
| 295 : rrtype_(rrtype), name_(name), active_(active), | 277 : rrtype_(rrtype), name_(name), client_(client), delegate_(delegate), |
| 296 alert_existing_records_(alert_existing_records), client_(client), | 278 started_(false) { |
| 297 delegate_(delegate), started_(false) { | |
| 298 } | 279 } |
| 299 | 280 |
| 300 bool MDnsListenerImpl::Start() { | 281 bool MDnsListenerImpl::Start() { |
| 301 DCHECK(!started_); | 282 DCHECK(!started_); |
| 302 | 283 |
| 303 if (!client_->AddListenRef()) return false; | 284 if (!client_->AddListenRef()) return false; |
| 304 started_ = true; | 285 started_ = true; |
| 305 | 286 |
| 306 client_->core()->AddListener(this, alert_existing_records_); | 287 client_->core()->AddListener(this); |
| 307 | 288 |
| 308 if (active_) SendQuery(false); // TODO(noamsml): Retry logic. | |
| 309 return true; | 289 return true; |
| 310 } | 290 } |
| 311 | 291 |
| 312 MDnsListenerImpl::~MDnsListenerImpl() { | 292 MDnsListenerImpl::~MDnsListenerImpl() { |
| 313 if (started_) { | 293 if (started_) { |
| 314 client_->core()->RemoveListener(this); | 294 client_->core()->RemoveListener(this); |
| 315 client_->SubtractListenRef(); | 295 client_->SubtractListenRef(); |
| 316 } | 296 } |
| 317 } | 297 } |
| 318 | 298 |
| 319 const std::string& MDnsListenerImpl::GetName() const { | 299 const std::string& MDnsListenerImpl::GetName() const { |
| 320 return name_; | 300 return name_; |
| 321 } | 301 } |
| 322 | 302 |
| 323 uint16 MDnsListenerImpl::GetType() const { | 303 uint16 MDnsListenerImpl::GetType() const { |
| 324 return rrtype_; | 304 return rrtype_; |
| 325 } | 305 } |
| 326 | 306 |
| 327 bool MDnsListenerImpl::IsActive() const { | |
| 328 return active_; | |
| 329 } | |
| 330 | |
| 331 bool MDnsListenerImpl::SendQuery(bool force_refresh_cache) { | |
| 332 DCHECK(started_); | |
| 333 // TODO(noamsml): Logic related to force_refresh_cache | |
| 334 if (name_.size() == 0) return false; | |
| 335 return client_->core()->SendQuery(rrtype_, name_); | |
| 336 } | |
| 337 | |
| 338 bool MDnsListenerImpl::QueryCache( | |
| 339 std::vector<const RecordParsed*>* records) const { | |
| 340 DCHECK(started_); | |
| 341 if (name_.size() == 0) return false; | |
| 342 client_->core()->QueryCache(rrtype_, name_, records); | |
| 343 return true; | |
| 344 } | |
| 345 | |
| 346 void MDnsListenerImpl::AlertDelegate(MDnsUpdateType update_type, | 307 void MDnsListenerImpl::AlertDelegate(MDnsUpdateType update_type, |
| 347 const RecordParsed* record) { | 308 const RecordParsed* record) { |
| 348 DCHECK(started_); | 309 DCHECK(started_); |
| 349 delegate_->OnRecordUpdate(update_type, record); | 310 delegate_->OnRecordUpdate(update_type, record); |
| 350 } | 311 } |
| 351 | 312 |
| 352 MDnsTransactionImpl::MDnsTransactionImpl( | 313 MDnsTransactionImpl::MDnsTransactionImpl( |
| 353 uint16 rrtype, | 314 uint16 rrtype, |
| 354 const std::string& name, | 315 const std::string& name, |
| 316 int flags, | |
| 355 const MDnsTransaction::ResultCallback& callback, | 317 const MDnsTransaction::ResultCallback& callback, |
| 356 MDnsClientImpl* client) | 318 MDnsClientImpl* client) |
| 357 : rrtype_(rrtype), name_(name), callback_(callback), client_(client), | 319 : rrtype_(rrtype), name_(name), callback_(callback), client_(client), |
| 358 started_(false) { | 320 started_(false), flags_(flags) { |
| 321 DCHECK((flags_ & kMDnsTransactionFlagMask) == flags_); | |
| 322 DCHECK(flags_ & kMDnsTransactionQueryCache || | |
| 323 flags_ & kMDnsTransactionQueryNetwork); | |
| 359 } | 324 } |
| 360 | 325 |
| 361 MDnsTransactionImpl::~MDnsTransactionImpl() { | 326 MDnsTransactionImpl::~MDnsTransactionImpl() { |
| 327 timeout_.Cancel(); | |
| 362 } | 328 } |
| 363 | 329 |
| 364 bool MDnsTransactionImpl::Start() { | 330 bool MDnsTransactionImpl::Start() { |
| 365 DCHECK(!started_); | 331 DCHECK(!started_); |
| 366 started_ = true; | 332 started_ = true; |
| 367 std::vector<const RecordParsed*> records; | 333 std::vector<const RecordParsed*> records; |
| 368 if (client_->core()) { | 334 base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr(); |
| 369 client_->core()->QueryCache(rrtype_, name_, &records); | 335 |
| 370 if (!records.empty()) { | 336 if (flags_ & kMDnsTransactionQueryCache) { |
| 371 TriggerCallback(kMDnsTransactionSuccess, records.front()); | 337 if (client_->core()) { |
| 372 return true; | 338 client_->core()->QueryCache(rrtype_, name_, &records); |
| 339 for (std::vector<const RecordParsed*>::iterator i = records.begin(); | |
| 340 i != records.end() && weak_this; ++i) { | |
| 341 weak_this->TriggerCallback(kMDnsTransactionRecord, records.front()); | |
| 342 } | |
| 373 } | 343 } |
| 374 } | 344 } |
| 375 | 345 |
| 376 listener_ = client_->CreateListener(rrtype_, name_, true /*active*/, | 346 if (!weak_this) return true; |
| 377 false /*alert existing*/, this); | |
| 378 listener_->Start(); | |
| 379 | 347 |
| 380 timeout_.Reset(base::Bind(&MDnsTransactionImpl::OnTimedOut, AsWeakPtr())); | 348 if (is_active() && flags_ & kMDnsTransactionQueryNetwork) { |
| 381 base::MessageLoop::current()->PostDelayedTask( | 349 listener_ = client_->CreateListener(rrtype_, name_, this); |
| 382 FROM_HERE, | 350 if (!listener_->Start()) return false; |
| 383 timeout_.callback(), | |
| 384 base::TimeDelta::FromSeconds(kMDnsTransactionTimeoutSeconds)); | |
| 385 | 351 |
| 386 return listener_.get() != NULL; | 352 DCHECK(client_->core()); |
| 353 if (!client_->core()->SendQuery(rrtype_, name_)) { | |
| 354 return false; | |
| 355 } | |
| 356 | |
| 357 timeout_.Reset(base::Bind(&MDnsTransactionImpl::SignalTransactionOver, | |
| 358 weak_this)); | |
| 359 base::MessageLoop::current()->PostDelayedTask( | |
| 360 FROM_HERE, | |
| 361 timeout_.callback(), | |
| 362 base::TimeDelta::FromSeconds(kMDnsTransactionNoResultsSeconds)); | |
| 363 | |
| 364 return listener_.get() != NULL; | |
| 365 } else { | |
| 366 // If this is a cache only query, signal that the transaction is over | |
| 367 // immediately. | |
| 368 SignalTransactionOver(); | |
| 369 } | |
| 370 | |
| 371 return true; | |
| 387 } | 372 } |
| 388 | 373 |
| 389 const std::string& MDnsTransactionImpl::GetName() const { | 374 const std::string& MDnsTransactionImpl::GetName() const { |
| 390 return name_; | 375 return name_; |
| 391 } | 376 } |
| 392 | 377 |
| 393 uint16 MDnsTransactionImpl::GetType() const { | 378 uint16 MDnsTransactionImpl::GetType() const { |
| 394 return rrtype_; | 379 return rrtype_; |
| 395 } | 380 } |
| 396 | 381 |
| 397 void MDnsTransactionImpl::CacheRecordFound(const RecordParsed* record) { | 382 void MDnsTransactionImpl::CacheRecordFound(const RecordParsed* record) { |
| 398 DCHECK(started_); | 383 DCHECK(started_); |
| 399 OnRecordUpdate(kMDnsRecordAdded, record); | 384 OnRecordUpdate(kMDnsRecordAdded, record); |
| 400 } | 385 } |
| 401 | 386 |
| 402 void MDnsTransactionImpl::TriggerCallback(MDnsTransactionResult result, | 387 void MDnsTransactionImpl::TriggerCallback(MDnsTransactionResult result, |
| 403 const RecordParsed* record) { | 388 const RecordParsed* record) { |
| 404 DCHECK(started_); | 389 DCHECK(started_); |
| 405 if (callback_.is_null()) return; | 390 if (!is_active()) return; |
| 406 | 391 |
| 407 // Ensure callback is run after touching all class state, so that | 392 // Ensure callback is run after touching all class state, so that |
| 408 // the callback can delete the transaction. | 393 // the callback can delete the transaction. |
| 409 MDnsTransaction::ResultCallback callback = callback_; | 394 MDnsTransaction::ResultCallback callback = callback_; |
| 410 | 395 |
| 396 if (flags_ & kMDnsTransactionSingleResult) { | |
| 397 Reset(); | |
| 398 } | |
| 399 | |
| 400 callback.Run(result, record); | |
| 401 } | |
| 402 | |
| 403 void MDnsTransactionImpl::Reset() { | |
| 411 callback_.Reset(); | 404 callback_.Reset(); |
| 412 listener_.reset(); | 405 listener_.reset(); |
| 413 timeout_.Cancel(); | 406 timeout_.Cancel(); |
| 414 | |
| 415 callback.Run(result, record); | |
| 416 } | 407 } |
| 417 | 408 |
| 418 void MDnsTransactionImpl::OnRecordUpdate(MDnsUpdateType update, | 409 void MDnsTransactionImpl::OnRecordUpdate(MDnsUpdateType update, |
| 419 const RecordParsed* record) { | 410 const RecordParsed* record) { |
| 420 DCHECK(started_); | 411 DCHECK(started_); |
| 421 if (update == kMDnsRecordAdded || update == kMDnsRecordChanged) { | 412 if (update == kMDnsRecordAdded || update == kMDnsRecordChanged) { |
| 422 TriggerCallback(kMDnsTransactionSuccess, record); | 413 TriggerCallback(kMDnsTransactionRecord, record); |
| 423 } | 414 } |
| 424 } | 415 } |
| 425 | 416 |
| 426 void MDnsTransactionImpl::OnTimedOut() { | 417 void MDnsTransactionImpl::SignalTransactionOver() { |
| 427 DCHECK(started_); | 418 DCHECK(started_); |
| 428 TriggerCallback(kMDnsTransactionTimeout, NULL); | 419 base::WeakPtr<MDnsTransactionImpl> weak_this = AsWeakPtr(); |
| 420 | |
| 421 if (flags_ & kMDnsTransactionSingleResult) { | |
| 422 TriggerCallback(kMDnsTransactionNoResults, NULL); | |
| 423 } else { | |
| 424 TriggerCallback(kMDnsTransactionDone, NULL); | |
| 425 } | |
| 426 | |
| 427 if (weak_this) { | |
| 428 weak_this->Reset(); | |
| 429 } | |
| 429 } | 430 } |
| 430 | 431 |
| 431 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { | 432 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { |
| 432 // TODO(noamsml): NSEC records not yet implemented | 433 // TODO(noamsml): NSEC records not yet implemented |
| 433 } | 434 } |
| 434 | 435 |
| 435 MDnsConnectionImpl::RecvLoop::RecvLoop( | 436 void MDnsTransactionImpl::OnCachePurged() { |
| 436 DatagramServerSocket* socket, MDnsConnectionImpl* connection) | 437 // TODO(noamsml): Cache purge situations not yet implemented |
| 437 : socket_(socket), connection_(connection), | |
| 438 response_(new DnsResponse(dns_protocol::kMaxMulticastSize)) { | |
| 439 } | 438 } |
| 440 | 439 |
| 441 MDnsConnectionImpl::RecvLoop::~RecvLoop() { | 440 MDnsConnectionImpl::SocketHandler::SocketHandler( |
| 441 MDnsConnectionImpl* connection, const IPEndPoint& multicast_addr) | |
| 442 : socket_owned_(new UDPServerSocket(NULL, NetLog::Source())), | |
| 443 socket_(socket_owned_.get()), connection_(connection), | |
| 444 response_(new DnsResponse(dns_protocol::kMaxMulticastSize)), | |
| 445 multicast_addr_(multicast_addr) { | |
| 442 } | 446 } |
| 443 | 447 |
| 444 void MDnsConnectionImpl::RecvLoop::DoLoop(int rv) { | 448 MDnsConnectionImpl::SocketHandler::SocketHandler( |
| 449 DatagramServerSocket* socket, | |
| 450 MDnsConnectionImpl* connection, const IPEndPoint& multicast_addr) | |
| 451 : socket_(socket), connection_(connection), | |
| 452 response_(new DnsResponse(dns_protocol::kMaxMulticastSize)), | |
| 453 multicast_addr_(multicast_addr) { | |
| 454 } | |
| 455 | |
| 456 | |
| 457 MDnsConnectionImpl::SocketHandler::~SocketHandler() { | |
| 458 } | |
| 459 | |
| 460 int MDnsConnectionImpl::SocketHandler::Start() { | |
| 461 int rv = BindSocket(); | |
| 462 if (rv != OK) { | |
| 463 return rv; | |
| 464 } | |
| 465 | |
| 466 return DoLoop(0); | |
| 467 } | |
| 468 | |
| 469 int MDnsConnectionImpl::SocketHandler::DoLoop(int rv) { | |
| 445 do { | 470 do { |
| 446 if (rv > 0) { | 471 if (rv > 0) { |
| 447 connection_->OnDatagramReceived(socket_, | 472 connection_->OnDatagramReceived(socket_, |
| 448 response_.get(), &recv_addr_, rv); | 473 response_.get(), &recv_addr_, rv); |
| 449 } | 474 } |
| 450 | 475 |
| 451 rv = socket_->RecvFrom( | 476 rv = socket_->RecvFrom( |
| 452 response_->io_buffer(), | 477 response_->io_buffer(), |
| 453 response_->io_buffer()->size(), | 478 response_->io_buffer()->size(), |
| 454 &recv_addr_, | 479 &recv_addr_, |
| 455 base::Bind(&MDnsConnectionImpl::RecvLoop::OnDatagramReceived, | 480 base::Bind(&MDnsConnectionImpl::SocketHandler::OnDatagramReceived, |
| 456 base::Unretained(this))); | 481 base::Unretained(this))); |
| 457 } while (rv > 0); | 482 } while (rv > 0); |
| 458 | 483 |
| 459 if (rv != ERR_IO_PENDING) { | 484 if (rv != ERR_IO_PENDING) { |
| 460 connection_->OnError(this, socket_, rv); | 485 return rv; |
| 486 } | |
| 487 | |
| 488 return OK; | |
| 489 } | |
| 490 | |
| 491 void MDnsConnectionImpl::SocketHandler::OnDatagramReceived(int rv) { | |
| 492 if (rv >= OK) { | |
| 493 rv = DoLoop(rv); | |
| 494 } | |
| 495 | |
| 496 if (rv != OK) { | |
| 497 connection_->OnError(this, rv); | |
| 461 } | 498 } |
| 462 } | 499 } |
| 463 | 500 |
| 464 void MDnsConnectionImpl::RecvLoop::OnDatagramReceived(int rv) { | 501 int MDnsConnectionImpl::SocketHandler::Send(IOBuffer* buffer, unsigned size) { |
| 465 DoLoop(rv); | 502 return socket_->SendTo( |
| 503 buffer, size, multicast_addr_, | |
| 504 base::Bind(&MDnsConnectionImpl::SocketHandler::SendDone, | |
| 505 base::Unretained(this) )); | |
| 466 } | 506 } |
| 467 | 507 |
| 508 void MDnsConnectionImpl::SocketHandler::SendDone(int sent) { | |
| 509 // TODO(noamsml): Retry logic. | |
| 510 } | |
| 511 | |
| 512 int MDnsConnectionImpl::SocketHandler::BindSocket() { | |
| 513 IPAddressNumber address_any; | |
| 514 address_any.resize(multicast_addr_.address().size(), 0); | |
| 515 | |
| 516 IPEndPoint bind_endpoint(address_any, multicast_addr_.port()); | |
| 517 | |
| 518 socket_->AllowAddressReuse(); | |
| 519 int rv = socket_->Listen(bind_endpoint); | |
| 520 | |
| 521 if (rv < OK) return rv; | |
| 522 | |
| 523 socket_->SetMulticastLoopbackMode(false); | |
| 524 | |
| 525 return socket_->JoinGroup(multicast_addr_.address()); | |
| 526 } | |
| 527 | |
| 528 | |
| 468 MDnsConnectionImpl::MDnsConnectionImpl(MDnsConnection::Delegate* delegate) | 529 MDnsConnectionImpl::MDnsConnectionImpl(MDnsConnection::Delegate* delegate) |
| 469 : socket_ipv4_(new UDPServerSocket(NULL, NetLog::Source())), | 530 : socket_handler_ipv4_(this, GetIPEndPoint(kMDnsMulticastGroupIPv4, |
|
szym
2013/06/10 21:58:28
If you always use this with the same port, why not
Noam Samuel
2013/06/11 20:35:03
Done.
| |
| 470 socket_ipv6_(new UDPServerSocket(NULL, NetLog::Source())), | 531 dns_protocol::kDefaultPortMulticast)), |
| 471 loop_ipv4_(socket_ipv4_.get(), this), | 532 socket_handler_ipv6_(this, GetIPEndPoint(kMDnsMulticastGroupIPv6, |
| 472 loop_ipv6_(socket_ipv6_.get(), this), | 533 dns_protocol::kDefaultPortMulticast)), |
| 534 delegate_(delegate) { | |
| 535 } | |
| 536 | |
| 537 MDnsConnectionImpl::MDnsConnectionImpl(DatagramServerSocket* socket_ipv4, | |
| 538 DatagramServerSocket* socket_ipv6, | |
| 539 MDnsConnection::Delegate* delegate) | |
| 540 : socket_handler_ipv4_(socket_ipv4, this, | |
| 541 GetIPEndPoint(kMDnsMulticastGroupIPv4, | |
| 542 dns_protocol::kDefaultPortMulticast)), | |
| 543 socket_handler_ipv6_(socket_ipv6, this, | |
| 544 GetIPEndPoint(kMDnsMulticastGroupIPv6, | |
| 545 dns_protocol::kDefaultPortMulticast)), | |
| 473 delegate_(delegate) { | 546 delegate_(delegate) { |
| 474 } | 547 } |
| 475 | 548 |
| 476 MDnsConnectionImpl::~MDnsConnectionImpl() { | 549 MDnsConnectionImpl::~MDnsConnectionImpl() { |
| 477 socket_ipv4_->Close(); | |
| 478 socket_ipv6_->Close(); | |
| 479 } | 550 } |
| 480 | 551 |
| 481 bool MDnsConnectionImpl::Init() { | 552 int MDnsConnectionImpl::Init() { |
| 482 if (!BindSocket(socket_ipv4_.get(), kIPv4AddressSize, | 553 int rv; |
| 483 kMDNSMulticastGroupIPv4)) | |
| 484 return false; | |
| 485 | 554 |
| 486 if (!BindSocket(socket_ipv6_.get(), kIPv6AddressSize, | 555 rv = socket_handler_ipv4_.Start(); |
| 487 kMDNSMulticastGroupIPv6)) | 556 if (rv != OK) return rv; |
| 488 return false; | 557 rv = socket_handler_ipv6_.Start(); |
| 489 | 558 if (rv != OK) return rv; |
| 490 loop_ipv4_.DoLoop(0); | |
| 491 loop_ipv6_.DoLoop(0); | |
| 492 | 559 |
| 493 return true; | 560 return true; |
| 494 } | 561 } |
| 495 | 562 |
| 496 bool MDnsConnectionImpl::Send(IOBuffer* buffer, unsigned size) { | 563 int MDnsConnectionImpl::Send(IOBuffer* buffer, unsigned size) { |
| 497 int rv = socket_ipv4_->SendTo( | 564 int rv; |
| 498 buffer, | |
| 499 size, | |
| 500 GetIPv4SendEndpoint(), | |
| 501 base::Bind(&MDnsConnectionImpl::SendDone, | |
| 502 base::Unretained(this) )); | |
| 503 if (rv < OK && rv != ERR_IO_PENDING) return false; | |
| 504 | 565 |
| 505 rv = socket_ipv6_->SendTo( | 566 rv = socket_handler_ipv4_.Send(buffer, size); |
| 506 buffer, | 567 if (rv < OK && rv != ERR_IO_PENDING) return rv; |
| 507 size, | |
| 508 GetIPv6SendEndpoint(), | |
| 509 base::Bind(&MDnsConnectionImpl::SendDone, | |
| 510 base::Unretained(this) )); | |
| 511 if (rv < OK && rv != ERR_IO_PENDING) return false; | |
| 512 | 568 |
| 513 return true; | 569 rv = socket_handler_ipv6_.Send(buffer, size); |
| 570 if (rv < OK && rv != ERR_IO_PENDING) return rv; | |
| 571 | |
| 572 return OK; | |
| 514 } | 573 } |
| 515 | 574 |
| 516 void MDnsConnectionImpl::SendDone(int sent) { | 575 void MDnsConnectionImpl::OnError(SocketHandler* loop, |
| 517 // TODO(noamsml): Queueing and retry logic. | 576 int error) { |
| 577 // TODO(noamsml): Specific handling of intermittent errors that can be handled | |
| 578 // in the connection. | |
| 579 delegate_->OnConnectionError(error); | |
| 518 } | 580 } |
| 519 | 581 |
| 520 void MDnsConnectionImpl::OnError(RecvLoop* loop, | 582 IPEndPoint MDnsConnectionImpl::GetIPEndPoint(const char* address, int port) { |
| 521 DatagramServerSocket* socket, | |
| 522 int error) { | |
| 523 // TODO(noamsml): Error handling. | |
| 524 } | |
| 525 | |
| 526 bool MDnsConnectionImpl::BindSocket( | |
| 527 DatagramServerSocket* socket, | |
| 528 int addr_size, | |
| 529 const char* multicast_group) { | |
| 530 IPAddressNumber address_any; | |
| 531 address_any.resize(addr_size, 0); | |
| 532 | |
| 533 IPAddressNumber multicast_group_number; | 583 IPAddressNumber multicast_group_number; |
| 534 | 584 bool success = ParseIPLiteralToNumber(address, |
| 535 IPEndPoint bind_endpoint(address_any, dns_protocol::kDefaultPortMulticast); | |
| 536 | |
| 537 bool success = ParseIPLiteralToNumber(multicast_group, | |
| 538 &multicast_group_number); | 585 &multicast_group_number); |
| 539 DCHECK(success); | 586 DCHECK(success); |
| 540 | 587 return IPEndPoint(multicast_group_number, port); |
| 541 socket->AllowAddressReuse(); | |
| 542 int status = socket->Listen(bind_endpoint); | |
| 543 | |
| 544 if (status < 0) | |
| 545 return false; | |
| 546 | |
| 547 socket->SetMulticastLoopbackMode(false); | |
| 548 | |
| 549 status = socket->JoinGroup(multicast_group_number); | |
| 550 | |
| 551 if (status < 0) | |
| 552 return false; | |
| 553 | |
| 554 return true; | |
| 555 } | |
| 556 | |
| 557 IPEndPoint MDnsConnectionImpl::GetIPv4SendEndpoint() { | |
| 558 IPAddressNumber multicast_group_number; | |
| 559 bool success = ParseIPLiteralToNumber(kMDNSMulticastGroupIPv4, | |
| 560 &multicast_group_number); | |
| 561 DCHECK(success); | |
| 562 return IPEndPoint(multicast_group_number, | |
| 563 dns_protocol::kDefaultPortMulticast); | |
| 564 } | |
| 565 | |
| 566 IPEndPoint MDnsConnectionImpl::GetIPv6SendEndpoint() { | |
| 567 IPAddressNumber multicast_group_number; | |
| 568 bool success = ParseIPLiteralToNumber(kMDNSMulticastGroupIPv6, | |
| 569 &multicast_group_number); | |
| 570 DCHECK(success); | |
| 571 return IPEndPoint(multicast_group_number, | |
| 572 dns_protocol::kDefaultPortMulticast); | |
| 573 } | 588 } |
| 574 | 589 |
| 575 void MDnsConnectionImpl::OnDatagramReceived( | 590 void MDnsConnectionImpl::OnDatagramReceived( |
| 576 DatagramServerSocket* socket, | 591 DatagramServerSocket* socket, |
| 577 DnsResponse* response, | 592 DnsResponse* response, |
| 578 IPEndPoint* recv_addr, | 593 IPEndPoint* recv_addr, |
| 579 int bytes_read) { | 594 int bytes_read) { |
| 580 // TODO(noamsml): More sophisticated error handling. | 595 // TODO(noamsml): More sophisticated error handling. |
| 581 DCHECK_GT(bytes_read, 0); | 596 DCHECK_GT(bytes_read, 0); |
| 582 delegate_->HandlePacket(response, bytes_read); | 597 delegate_->HandlePacket(response, bytes_read); |
| 583 } | 598 } |
| 584 | 599 |
| 585 MDnsConnectionImplFactory::MDnsConnectionImplFactory() { | 600 MDnsConnectionImplFactory::MDnsConnectionImplFactory() { |
| 586 } | 601 } |
| 587 | 602 |
| 588 MDnsConnectionImplFactory::~MDnsConnectionImplFactory() { | 603 MDnsConnectionImplFactory::~MDnsConnectionImplFactory() { |
| 589 } | 604 } |
| 590 | 605 |
| 591 scoped_ptr<MDnsConnection> MDnsConnectionImplFactory::CreateConnection( | 606 scoped_ptr<MDnsConnection> MDnsConnectionImplFactory::CreateConnection( |
| 592 MDnsConnection::Delegate* delegate) { | 607 MDnsConnection::Delegate* delegate) { |
| 593 return scoped_ptr<MDnsConnection>(new MDnsConnectionImpl(delegate)); | 608 return scoped_ptr<MDnsConnection>(new MDnsConnectionImpl(delegate)); |
| 594 } | 609 } |
| 595 | 610 |
| 596 } // namespace net | 611 } // namespace net |
| OLD | NEW |