OLD | NEW |
---|---|
1 // Copyright 2013 The Chromium Authors. All rights reserved. | 1 // Copyright 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/message_loop_proxy.h" | 8 #include "base/message_loop/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/record_rdata.h" | 16 #include "net/dns/record_rdata.h" |
17 #include "net/udp/datagram_socket.h" | 17 #include "net/udp/datagram_socket.h" |
18 | 18 |
19 // TODO(gene): Remove this temporary method of disabling NSEC support once it | 19 // TODO(gene): Remove this temporary method of disabling NSEC support once it |
20 // becomes clear whether this feature should be | 20 // becomes clear whether this feature should be |
21 // supported. http://crbug.com/255232 | 21 // supported. http://crbug.com/255232 |
22 #define ENABLE_NSEC | 22 #define ENABLE_NSEC |
23 | 23 |
24 namespace net { | 24 namespace net { |
25 | 25 |
26 namespace { | 26 namespace { |
27 const unsigned MDnsTransactionTimeoutSeconds = 3; | 27 const unsigned MDnsTransactionTimeoutSeconds = 3; |
28 } | 28 } |
29 | 29 |
30 MDnsConnection::SocketHandler::SocketHandler( | 30 MDnsConnection::SocketHandler::SocketHandler(scoped_ptr<Socket> socket, |
31 MDnsConnection* connection, const IPEndPoint& multicast_addr, | 31 MDnsConnection* connection) |
32 MDnsConnection::SocketFactory* socket_factory) | 32 : socket_(socket.Pass()), |
33 : socket_(socket_factory->CreateSocket()), connection_(connection), | 33 connection_(connection), |
34 response_(new DnsResponse(dns_protocol::kMaxMulticastSize)), | 34 response_(dns_protocol::kMaxMulticastSize) { |
35 multicast_addr_(multicast_addr) { | |
36 } | 35 } |
37 | 36 |
38 MDnsConnection::SocketHandler::~SocketHandler() { | 37 MDnsConnection::SocketHandler::~SocketHandler() { |
39 } | 38 } |
40 | 39 |
41 int MDnsConnection::SocketHandler::Start() { | 40 int MDnsConnection::SocketHandler::Start() { |
42 return DoLoop(0); | 41 return DoLoop(0); |
43 } | 42 } |
44 | 43 |
45 int MDnsConnection::SocketHandler::DoLoop(int rv) { | 44 int MDnsConnection::SocketHandler::DoLoop(int rv) { |
46 do { | 45 do { |
47 if (rv > 0) | 46 if (rv > 0) |
48 connection_->OnDatagramReceived(response_.get(), recv_addr_, rv); | 47 connection_->OnDatagramReceived(&response_, recv_addr_, rv); |
49 | 48 |
50 rv = socket_->RecvFrom( | 49 rv = socket_->RecvFrom( |
51 response_->io_buffer(), | 50 response_.io_buffer(), |
52 response_->io_buffer()->size(), | 51 response_.io_buffer()->size(), |
53 &recv_addr_, | 52 &recv_addr_, |
54 base::Bind(&MDnsConnection::SocketHandler::OnDatagramReceived, | 53 base::Bind(&MDnsConnection::SocketHandler::OnDatagramReceived, |
55 base::Unretained(this))); | 54 base::Unretained(this))); |
56 } while (rv > 0); | 55 } while (rv > 0); |
57 | 56 |
58 if (rv != ERR_IO_PENDING) | 57 if (rv != ERR_IO_PENDING) |
59 return rv; | 58 return rv; |
60 | 59 |
61 return OK; | 60 return OK; |
62 } | 61 } |
63 | 62 |
64 void MDnsConnection::SocketHandler::OnDatagramReceived(int rv) { | 63 void MDnsConnection::SocketHandler::OnDatagramReceived(int rv) { |
65 if (rv >= OK) | 64 if (rv >= OK) |
66 rv = DoLoop(rv); | 65 rv = DoLoop(rv); |
67 | 66 |
68 if (rv != OK) | 67 if (rv != OK) |
69 connection_->OnError(this, rv); | 68 connection_->OnError(this, rv); |
70 } | 69 } |
71 | 70 |
72 int MDnsConnection::SocketHandler::Send(IOBuffer* buffer, unsigned size) { | 71 int MDnsConnection::SocketHandler::Send(IOBuffer* buffer, unsigned size) { |
73 return socket_->SendTo( | 72 return socket_->SendTo(buffer, size, |
74 buffer, size, multicast_addr_, | 73 base::Bind(&MDnsConnection::SocketHandler::SendDone, |
75 base::Bind(&MDnsConnection::SocketHandler::SendDone, | 74 base::Unretained(this) )); |
76 base::Unretained(this) )); | |
77 } | 75 } |
78 | 76 |
79 void MDnsConnection::SocketHandler::SendDone(int rv) { | 77 void MDnsConnection::SocketHandler::SendDone(int rv) { |
80 // TODO(noamsml): Retry logic. | 78 // TODO(noamsml): Retry logic. |
81 } | 79 } |
82 | 80 |
83 int MDnsConnection::SocketHandler::Bind() { | |
84 IPAddressNumber address_any(multicast_addr_.address().size()); | |
85 | |
86 IPEndPoint bind_endpoint(address_any, multicast_addr_.port()); | |
87 | |
88 socket_->AllowAddressReuse(); | |
89 int rv = socket_->Listen(bind_endpoint); | |
90 | |
91 if (rv < OK) return rv; | |
92 | |
93 socket_->SetMulticastLoopbackMode(false); | |
94 | |
95 return socket_->JoinGroup(multicast_addr_.address()); | |
96 } | |
97 | |
98 MDnsConnection::MDnsConnection(MDnsConnection::Delegate* delegate) : | 81 MDnsConnection::MDnsConnection(MDnsConnection::Delegate* delegate) : |
99 delegate_(delegate) { | 82 delegate_(delegate) { |
100 } | 83 } |
101 | 84 |
102 MDnsConnection::~MDnsConnection() { | 85 MDnsConnection::~MDnsConnection() { |
103 } | 86 } |
104 | 87 |
105 bool MDnsConnection::Init(MDnsConnection::SocketFactory* socket_factory) { | 88 bool MDnsConnection::Init(MDnsConnection::SocketFactory* socket_factory) { |
106 // TODO(vitalybuka): crbug.com/297690 Make socket_factory return list | 89 ScopedVector<Socket> sockets; |
107 // of initialized sockets. | 90 socket_factory->CreateSockets(&sockets); |
108 socket_handlers_.push_back( | |
109 new SocketHandler(this, GetMDnsIPEndPoint(ADDRESS_FAMILY_IPV4), | |
110 socket_factory)); | |
111 socket_handlers_.push_back( | |
112 new SocketHandler(this, GetMDnsIPEndPoint(ADDRESS_FAMILY_IPV6), | |
113 socket_factory)); | |
114 | 91 |
115 for (size_t i = 0; i < socket_handlers_.size();) { | 92 for (size_t i = 0; i < sockets.size(); ++i) { |
116 int rv = socket_handlers_[i]->Bind(); | 93 socket_handlers_.push_back( |
szym
2013/11/27 00:28:09
Empty sockets (which failed to bind in CreateSocke
Vitaly Buka (NO REVIEWS)
2013/11/27 00:45:45
CreateSockets should filter. That was initial idea
| |
117 if (rv != OK) { | 94 new MDnsConnection::SocketHandler(make_scoped_ptr(sockets[i]), this)); |
118 socket_handlers_.erase(socket_handlers_.begin() + i); | |
119 VLOG(1) << "Bind failed, socket=" << i << ", error=" << rv; | |
120 } else { | |
121 ++i; | |
122 } | |
123 } | 95 } |
96 sockets.weak_clear(); | |
124 | 97 |
125 // All unbound sockets need to be bound before processing untrusted input. | 98 // All unbound sockets need to be bound before processing untrusted input. |
126 // This is done for security reasons, so that an attacker can't get an unbound | 99 // This is done for security reasons, so that an attacker can't get an unbound |
127 // socket. | 100 // socket. |
128 for (size_t i = 0; i < socket_handlers_.size();) { | 101 for (size_t i = 0; i < socket_handlers_.size();) { |
129 int rv = socket_handlers_[i]->Start(); | 102 int rv = socket_handlers_[i]->Start(); |
130 if (rv != OK) { | 103 if (rv != OK) { |
131 socket_handlers_.erase(socket_handlers_.begin() + i); | 104 socket_handlers_.erase(socket_handlers_.begin() + i); |
132 VLOG(1) << "Start failed, socket=" << i << ", error=" << rv; | 105 VLOG(1) << "Start failed, socket=" << i << ", error=" << rv; |
133 } else { | 106 } else { |
(...skipping 26 matching lines...) Expand all Loading... | |
160 | 133 |
161 void MDnsConnection::OnDatagramReceived( | 134 void MDnsConnection::OnDatagramReceived( |
162 DnsResponse* response, | 135 DnsResponse* response, |
163 const IPEndPoint& recv_addr, | 136 const IPEndPoint& recv_addr, |
164 int bytes_read) { | 137 int bytes_read) { |
165 // TODO(noamsml): More sophisticated error handling. | 138 // TODO(noamsml): More sophisticated error handling. |
166 DCHECK_GT(bytes_read, 0); | 139 DCHECK_GT(bytes_read, 0); |
167 delegate_->HandlePacket(response, bytes_read); | 140 delegate_->HandlePacket(response, bytes_read); |
168 } | 141 } |
169 | 142 |
143 class SocketImpl : public MDnsConnection::Socket { | |
144 public: | |
145 explicit SocketImpl(const IPEndPoint& multicast_addr) | |
146 : multicast_addr_(multicast_addr), | |
147 socket_(NULL, NetLog::Source()) {}; | |
148 virtual ~SocketImpl() {}; | |
149 | |
150 int Bind() { | |
151 IPAddressNumber address_any(multicast_addr_.address().size()); | |
152 IPEndPoint bind_endpoint(address_any, multicast_addr_.port()); | |
153 | |
154 socket_.AllowAddressReuse(); | |
155 int rv = socket_.Listen(bind_endpoint); | |
156 if (rv < OK) | |
157 return rv; | |
158 | |
159 socket_.SetMulticastLoopbackMode(false); | |
160 return socket_.JoinGroup(multicast_addr_.address()); | |
161 } | |
162 | |
163 virtual int RecvFrom(IOBuffer* buf, | |
164 int buf_len, | |
165 IPEndPoint* address, | |
166 const CompletionCallback& callback) OVERRIDE { | |
167 return socket_.RecvFrom(buf, buf_len, address, callback); | |
168 } | |
169 | |
170 virtual int SendTo(IOBuffer* buf, | |
171 int buf_len, | |
172 const CompletionCallback& callback) OVERRIDE { | |
173 return socket_.SendTo(buf, buf_len, multicast_addr_, callback); | |
174 } | |
175 | |
176 private: | |
177 IPEndPoint multicast_addr_; | |
178 UDPServerSocket socket_; | |
179 | |
180 DISALLOW_COPY_AND_ASSIGN(SocketImpl); | |
181 }; | |
182 | |
170 class MDnsConnectionSocketFactoryImpl | 183 class MDnsConnectionSocketFactoryImpl |
171 : public MDnsConnection::SocketFactory { | 184 : public MDnsConnection::SocketFactory { |
172 public: | 185 public: |
173 MDnsConnectionSocketFactoryImpl(); | 186 MDnsConnectionSocketFactoryImpl() {}; |
174 virtual ~MDnsConnectionSocketFactoryImpl(); | 187 virtual ~MDnsConnectionSocketFactoryImpl() {}; |
175 | 188 |
176 virtual scoped_ptr<DatagramServerSocket> CreateSocket() OVERRIDE; | 189 virtual void CreateSockets( |
190 ScopedVector<MDnsConnection::Socket>* sockets) OVERRIDE { | |
191 sockets->push_back(CreateSocket(ADDRESS_FAMILY_IPV4).release()); | |
192 sockets->push_back(CreateSocket(ADDRESS_FAMILY_IPV6).release()); | |
193 } | |
194 | |
195 private: | |
196 scoped_ptr<MDnsConnection::Socket> CreateSocket( | |
197 AddressFamily address_family) { | |
198 scoped_ptr<SocketImpl> socket( | |
199 new SocketImpl(GetMDnsIPEndPoint(address_family))); | |
200 int rv = socket->Bind(); | |
201 if (rv != OK) { | |
202 VLOG(1) << "Bind failed, family=" << address_family << ", error=" << rv; | |
203 socket.reset(); | |
204 } | |
205 return socket.PassAs<MDnsConnection::Socket>(); | |
206 } | |
207 | |
208 DISALLOW_COPY_AND_ASSIGN(MDnsConnectionSocketFactoryImpl); | |
177 }; | 209 }; |
178 | 210 |
179 MDnsConnectionSocketFactoryImpl::MDnsConnectionSocketFactoryImpl() { | |
180 } | |
181 | |
182 MDnsConnectionSocketFactoryImpl::~MDnsConnectionSocketFactoryImpl() { | |
183 } | |
184 | |
185 scoped_ptr<DatagramServerSocket> | |
186 MDnsConnectionSocketFactoryImpl::CreateSocket() { | |
187 return scoped_ptr<DatagramServerSocket>(new UDPServerSocket( | |
188 NULL, NetLog::Source())); | |
189 } | |
190 | |
191 // static | 211 // static |
192 scoped_ptr<MDnsConnection::SocketFactory> | 212 scoped_ptr<MDnsConnection::SocketFactory> |
193 MDnsConnection::SocketFactory::CreateDefault() { | 213 MDnsConnection::SocketFactory::CreateDefault() { |
194 return scoped_ptr<MDnsConnection::SocketFactory>( | 214 return scoped_ptr<MDnsConnection::SocketFactory>( |
195 new MDnsConnectionSocketFactoryImpl); | 215 new MDnsConnectionSocketFactoryImpl); |
196 } | 216 } |
197 | 217 |
198 MDnsClientImpl::Core::Core(MDnsClientImpl* client) | 218 MDnsClientImpl::Core::Core(MDnsClientImpl* client) |
199 : client_(client), connection_(new MDnsConnection(this)) { | 219 : client_(client), connection_(new MDnsConnection(this)) { |
200 } | 220 } |
(...skipping 463 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... | |
664 | 684 |
665 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { | 685 void MDnsTransactionImpl::OnNsecRecord(const std::string& name, unsigned type) { |
666 TriggerCallback(RESULT_NSEC, NULL); | 686 TriggerCallback(RESULT_NSEC, NULL); |
667 } | 687 } |
668 | 688 |
669 void MDnsTransactionImpl::OnCachePurged() { | 689 void MDnsTransactionImpl::OnCachePurged() { |
670 // TODO(noamsml): Cache purge situations not yet implemented | 690 // TODO(noamsml): Cache purge situations not yet implemented |
671 } | 691 } |
672 | 692 |
673 } // namespace net | 693 } // namespace net |
OLD | NEW |