Chromium Code Reviews
chromiumcodereview-hr@appspot.gserviceaccount.com (chromiumcodereview-hr) | Please choose your nickname with Settings | Help | Chromium Project | Gerrit Changes | Sign out
(450)

Side by Side Diff: net/udp/udp_socket_posix.cc

Issue 2508593002: net: move udp directory into socket (Closed)
Patch Set: revert sys/socket.h change Created 4 years, 1 month ago
Use n/p to move between diff chunks; N/P to move between comments. Draft comments are only viewable by you.
Jump to:
View unified diff | Download patch
« no previous file with comments | « net/udp/udp_socket_posix.h ('k') | net/udp/udp_socket_unittest.cc » ('j') | no next file with comments »
Toggle Intra-line Diffs ('i') | Expand Comments ('e') | Collapse Comments ('c') | Show Comments Hide Comments ('s')
OLDNEW
(Empty)
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
3 // found in the LICENSE file.
4
5 #include "net/udp/udp_socket_posix.h"
6
7 #include <errno.h>
8 #include <fcntl.h>
9 #include <net/if.h>
10 #include <netdb.h>
11 #include <netinet/in.h>
12 #include <sys/ioctl.h>
13 #include <sys/socket.h>
14
15 #include "base/callback.h"
16 #include "base/debug/alias.h"
17 #include "base/files/file_util.h"
18 #include "base/logging.h"
19 #include "base/message_loop/message_loop.h"
20 #include "base/metrics/histogram_macros.h"
21 #include "base/posix/eintr_wrapper.h"
22 #include "base/rand_util.h"
23 #include "base/trace_event/trace_event.h"
24 #include "net/base/io_buffer.h"
25 #include "net/base/ip_address.h"
26 #include "net/base/ip_endpoint.h"
27 #include "net/base/net_errors.h"
28 #include "net/base/network_activity_monitor.h"
29 #include "net/base/sockaddr_storage.h"
30 #include "net/log/net_log.h"
31 #include "net/log/net_log_event_type.h"
32 #include "net/log/net_log_source.h"
33 #include "net/log/net_log_source_type.h"
34 #include "net/socket/socket_descriptor.h"
35 #include "net/udp/udp_net_log_parameters.h"
36
37 #if defined(OS_ANDROID)
38 #include <dlfcn.h>
39 // This was added in Lollipop to dlfcn.h
40 #define RTLD_NOLOAD 4
41 #include "base/android/build_info.h"
42 #include "base/native_library.h"
43 #include "base/strings/utf_string_conversions.h"
44 #endif
45
46 namespace net {
47
48 namespace {
49
50 const int kBindRetries = 10;
51 const int kPortStart = 1024;
52 const int kPortEnd = 65535;
53
54 #if defined(OS_MACOSX)
55
56 // Returns IPv4 address in network order.
57 int GetIPv4AddressFromIndex(int socket, uint32_t index, uint32_t* address) {
58 if (!index) {
59 *address = htonl(INADDR_ANY);
60 return OK;
61 }
62 ifreq ifr;
63 ifr.ifr_addr.sa_family = AF_INET;
64 if (!if_indextoname(index, ifr.ifr_name))
65 return MapSystemError(errno);
66 int rv = ioctl(socket, SIOCGIFADDR, &ifr);
67 if (rv == -1)
68 return MapSystemError(errno);
69 *address = reinterpret_cast<sockaddr_in*>(&ifr.ifr_addr)->sin_addr.s_addr;
70 return OK;
71 }
72
73 #endif // OS_MACOSX
74
75 } // namespace
76
77 UDPSocketPosix::UDPSocketPosix(DatagramSocket::BindType bind_type,
78 const RandIntCallback& rand_int_cb,
79 net::NetLog* net_log,
80 const net::NetLogSource& source)
81 : socket_(kInvalidSocket),
82 addr_family_(0),
83 is_connected_(false),
84 socket_options_(SOCKET_OPTION_MULTICAST_LOOP),
85 multicast_interface_(0),
86 multicast_time_to_live_(1),
87 bind_type_(bind_type),
88 rand_int_cb_(rand_int_cb),
89 read_watcher_(this),
90 write_watcher_(this),
91 read_buf_len_(0),
92 recv_from_address_(NULL),
93 write_buf_len_(0),
94 net_log_(NetLogWithSource::Make(net_log, NetLogSourceType::UDP_SOCKET)),
95 bound_network_(NetworkChangeNotifier::kInvalidNetworkHandle) {
96 net_log_.BeginEvent(NetLogEventType::SOCKET_ALIVE,
97 source.ToEventParametersCallback());
98 if (bind_type == DatagramSocket::RANDOM_BIND)
99 DCHECK(!rand_int_cb.is_null());
100 }
101
102 UDPSocketPosix::~UDPSocketPosix() {
103 Close();
104 net_log_.EndEvent(NetLogEventType::SOCKET_ALIVE);
105 }
106
107 int UDPSocketPosix::Open(AddressFamily address_family) {
108 DCHECK(CalledOnValidThread());
109 DCHECK_EQ(socket_, kInvalidSocket);
110
111 addr_family_ = ConvertAddressFamily(address_family);
112 socket_ = CreatePlatformSocket(addr_family_, SOCK_DGRAM, 0);
113 if (socket_ == kInvalidSocket)
114 return MapSystemError(errno);
115 if (!base::SetNonBlocking(socket_)) {
116 const int err = MapSystemError(errno);
117 Close();
118 return err;
119 }
120 return OK;
121 }
122
123 void UDPSocketPosix::Close() {
124 DCHECK(CalledOnValidThread());
125
126 if (socket_ == kInvalidSocket)
127 return;
128
129 // Zero out any pending read/write callback state.
130 read_buf_ = NULL;
131 read_buf_len_ = 0;
132 read_callback_.Reset();
133 recv_from_address_ = NULL;
134 write_buf_ = NULL;
135 write_buf_len_ = 0;
136 write_callback_.Reset();
137 send_to_address_.reset();
138
139 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
140 DCHECK(ok);
141 ok = write_socket_watcher_.StopWatchingFileDescriptor();
142 DCHECK(ok);
143
144 PCHECK(IGNORE_EINTR(close(socket_)) == 0);
145
146 socket_ = kInvalidSocket;
147 addr_family_ = 0;
148 is_connected_ = false;
149 }
150
151 int UDPSocketPosix::GetPeerAddress(IPEndPoint* address) const {
152 DCHECK(CalledOnValidThread());
153 DCHECK(address);
154 if (!is_connected())
155 return ERR_SOCKET_NOT_CONNECTED;
156
157 if (!remote_address_.get()) {
158 SockaddrStorage storage;
159 if (getpeername(socket_, storage.addr, &storage.addr_len))
160 return MapSystemError(errno);
161 std::unique_ptr<IPEndPoint> address(new IPEndPoint());
162 if (!address->FromSockAddr(storage.addr, storage.addr_len))
163 return ERR_ADDRESS_INVALID;
164 remote_address_.reset(address.release());
165 }
166
167 *address = *remote_address_;
168 return OK;
169 }
170
171 int UDPSocketPosix::GetLocalAddress(IPEndPoint* address) const {
172 DCHECK(CalledOnValidThread());
173 DCHECK(address);
174 if (!is_connected())
175 return ERR_SOCKET_NOT_CONNECTED;
176
177 if (!local_address_.get()) {
178 SockaddrStorage storage;
179 if (getsockname(socket_, storage.addr, &storage.addr_len))
180 return MapSystemError(errno);
181 std::unique_ptr<IPEndPoint> address(new IPEndPoint());
182 if (!address->FromSockAddr(storage.addr, storage.addr_len))
183 return ERR_ADDRESS_INVALID;
184 local_address_.reset(address.release());
185 net_log_.AddEvent(
186 NetLogEventType::UDP_LOCAL_ADDRESS,
187 CreateNetLogUDPConnectCallback(local_address_.get(), bound_network_));
188 }
189
190 *address = *local_address_;
191 return OK;
192 }
193
194 int UDPSocketPosix::Read(IOBuffer* buf,
195 int buf_len,
196 const CompletionCallback& callback) {
197 return RecvFrom(buf, buf_len, NULL, callback);
198 }
199
200 int UDPSocketPosix::RecvFrom(IOBuffer* buf,
201 int buf_len,
202 IPEndPoint* address,
203 const CompletionCallback& callback) {
204 DCHECK(CalledOnValidThread());
205 DCHECK_NE(kInvalidSocket, socket_);
206 CHECK(read_callback_.is_null());
207 DCHECK(!recv_from_address_);
208 DCHECK(!callback.is_null()); // Synchronous operation not supported
209 DCHECK_GT(buf_len, 0);
210
211 int nread = InternalRecvFrom(buf, buf_len, address);
212 if (nread != ERR_IO_PENDING)
213 return nread;
214
215 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
216 socket_, true, base::MessageLoopForIO::WATCH_READ,
217 &read_socket_watcher_, &read_watcher_)) {
218 PLOG(ERROR) << "WatchFileDescriptor failed on read";
219 int result = MapSystemError(errno);
220 LogRead(result, NULL, 0, NULL);
221 return result;
222 }
223
224 read_buf_ = buf;
225 read_buf_len_ = buf_len;
226 recv_from_address_ = address;
227 read_callback_ = callback;
228 return ERR_IO_PENDING;
229 }
230
231 int UDPSocketPosix::Write(IOBuffer* buf,
232 int buf_len,
233 const CompletionCallback& callback) {
234 return SendToOrWrite(buf, buf_len, NULL, callback);
235 }
236
237 int UDPSocketPosix::SendTo(IOBuffer* buf,
238 int buf_len,
239 const IPEndPoint& address,
240 const CompletionCallback& callback) {
241 return SendToOrWrite(buf, buf_len, &address, callback);
242 }
243
244 int UDPSocketPosix::SendToOrWrite(IOBuffer* buf,
245 int buf_len,
246 const IPEndPoint* address,
247 const CompletionCallback& callback) {
248 DCHECK(CalledOnValidThread());
249 DCHECK_NE(kInvalidSocket, socket_);
250 CHECK(write_callback_.is_null());
251 DCHECK(!callback.is_null()); // Synchronous operation not supported
252 DCHECK_GT(buf_len, 0);
253
254 int result = InternalSendTo(buf, buf_len, address);
255 if (result != ERR_IO_PENDING)
256 return result;
257
258 if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
259 socket_, true, base::MessageLoopForIO::WATCH_WRITE,
260 &write_socket_watcher_, &write_watcher_)) {
261 DVLOG(1) << "WatchFileDescriptor failed on write, errno " << errno;
262 int result = MapSystemError(errno);
263 LogWrite(result, NULL, NULL);
264 return result;
265 }
266
267 write_buf_ = buf;
268 write_buf_len_ = buf_len;
269 DCHECK(!send_to_address_.get());
270 if (address) {
271 send_to_address_.reset(new IPEndPoint(*address));
272 }
273 write_callback_ = callback;
274 return ERR_IO_PENDING;
275 }
276
277 int UDPSocketPosix::Connect(const IPEndPoint& address) {
278 DCHECK_NE(socket_, kInvalidSocket);
279 net_log_.BeginEvent(NetLogEventType::UDP_CONNECT,
280 CreateNetLogUDPConnectCallback(&address, bound_network_));
281 int rv = InternalConnect(address);
282 net_log_.EndEventWithNetErrorCode(NetLogEventType::UDP_CONNECT, rv);
283 is_connected_ = (rv == OK);
284 return rv;
285 }
286
287 int UDPSocketPosix::InternalConnect(const IPEndPoint& address) {
288 DCHECK(CalledOnValidThread());
289 DCHECK(!is_connected());
290 DCHECK(!remote_address_.get());
291
292 int rv = 0;
293 if (bind_type_ == DatagramSocket::RANDOM_BIND) {
294 // Construct IPAddress of appropriate size (IPv4 or IPv6) of 0s,
295 // representing INADDR_ANY or in6addr_any.
296 size_t addr_size = address.GetSockAddrFamily() == AF_INET
297 ? IPAddress::kIPv4AddressSize
298 : IPAddress::kIPv6AddressSize;
299 rv = RandomBind(IPAddress::AllZeros(addr_size));
300 }
301 // else connect() does the DatagramSocket::DEFAULT_BIND
302
303 if (rv < 0) {
304 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketRandomBindErrorCode", -rv);
305 return rv;
306 }
307
308 SockaddrStorage storage;
309 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
310 return ERR_ADDRESS_INVALID;
311
312 rv = HANDLE_EINTR(connect(socket_, storage.addr, storage.addr_len));
313 if (rv < 0)
314 return MapSystemError(errno);
315
316 remote_address_.reset(new IPEndPoint(address));
317 return rv;
318 }
319
320 int UDPSocketPosix::Bind(const IPEndPoint& address) {
321 DCHECK_NE(socket_, kInvalidSocket);
322 DCHECK(CalledOnValidThread());
323 DCHECK(!is_connected());
324
325 int rv = SetMulticastOptions();
326 if (rv < 0)
327 return rv;
328
329 rv = DoBind(address);
330 if (rv < 0)
331 return rv;
332
333 is_connected_ = true;
334 local_address_.reset();
335 return rv;
336 }
337
338 int UDPSocketPosix::BindToNetwork(
339 NetworkChangeNotifier::NetworkHandle network) {
340 DCHECK_NE(socket_, kInvalidSocket);
341 DCHECK(CalledOnValidThread());
342 DCHECK(!is_connected());
343 if (network == NetworkChangeNotifier::kInvalidNetworkHandle)
344 return ERR_INVALID_ARGUMENT;
345 #if defined(OS_ANDROID)
346 // Android prior to Lollipop didn't have support for binding sockets to
347 // networks.
348 if (base::android::BuildInfo::GetInstance()->sdk_int() <
349 base::android::SDK_VERSION_LOLLIPOP) {
350 return ERR_NOT_IMPLEMENTED;
351 }
352 int rv;
353 // On Android M and newer releases use supported NDK API. On Android L use
354 // setNetworkForSocket from libnetd_client.so.
355 if (base::android::BuildInfo::GetInstance()->sdk_int() >=
356 base::android::SDK_VERSION_MARSHMALLOW) {
357 // See declaration of android_setsocknetwork() here:
358 // http://androidxref.com/6.0.0_r1/xref/development/ndk/platforms/android-M/ include/android/multinetwork.h#65
359 // Function cannot be called directly as it will cause app to fail to load
360 // on pre-marshmallow devices.
361 typedef int (*MarshmallowSetNetworkForSocket)(int64_t netId, int socketFd);
362 static MarshmallowSetNetworkForSocket marshmallowSetNetworkForSocket;
363 // This is racy, but all racers should come out with the same answer so it
364 // shouldn't matter.
365 if (!marshmallowSetNetworkForSocket) {
366 base::FilePath file(base::GetNativeLibraryName("android"));
367 void* dl = dlopen(file.value().c_str(), RTLD_NOW);
368 marshmallowSetNetworkForSocket =
369 reinterpret_cast<MarshmallowSetNetworkForSocket>(
370 dlsym(dl, "android_setsocknetwork"));
371 }
372 if (!marshmallowSetNetworkForSocket)
373 return ERR_NOT_IMPLEMENTED;
374 rv = marshmallowSetNetworkForSocket(network, socket_);
375 if (rv)
376 rv = errno;
377 } else {
378 // NOTE(pauljensen): This does rely on Android implementation details, but
379 // they won't change because Lollipop is already released.
380 typedef int (*LollipopSetNetworkForSocket)(unsigned netId, int socketFd);
381 static LollipopSetNetworkForSocket lollipopSetNetworkForSocket;
382 // This is racy, but all racers should come out with the same answer so it
383 // shouldn't matter.
384 if (!lollipopSetNetworkForSocket) {
385 // Android's netd client library should always be loaded in our address
386 // space as it shims socket() which was used to create |socket_|.
387 base::FilePath file(base::GetNativeLibraryName("netd_client"));
388 // Use RTLD_NOW to match Android's prior loading of the library:
389 // http://androidxref.com/6.0.0_r5/xref/bionic/libc/bionic/NetdClient.cpp# 37
390 // Use RTLD_NOLOAD to assert that the library is already loaded and
391 // avoid doing any disk IO.
392 void* dl = dlopen(file.value().c_str(), RTLD_NOW | RTLD_NOLOAD);
393 lollipopSetNetworkForSocket =
394 reinterpret_cast<LollipopSetNetworkForSocket>(
395 dlsym(dl, "setNetworkForSocket"));
396 }
397 if (!lollipopSetNetworkForSocket)
398 return ERR_NOT_IMPLEMENTED;
399 rv = -lollipopSetNetworkForSocket(network, socket_);
400 }
401 // If |network| has since disconnected, |rv| will be ENONET. Surface this as
402 // ERR_NETWORK_CHANGED, rather than MapSystemError(ENONET) which gives back
403 // the less descriptive ERR_FAILED.
404 if (rv == ENONET)
405 return ERR_NETWORK_CHANGED;
406 if (rv == 0)
407 bound_network_ = network;
408 return MapSystemError(rv);
409 #else
410 NOTIMPLEMENTED();
411 return ERR_NOT_IMPLEMENTED;
412 #endif
413 }
414
415 int UDPSocketPosix::SetReceiveBufferSize(int32_t size) {
416 DCHECK_NE(socket_, kInvalidSocket);
417 DCHECK(CalledOnValidThread());
418 int rv = setsockopt(socket_, SOL_SOCKET, SO_RCVBUF,
419 reinterpret_cast<const char*>(&size), sizeof(size));
420 return rv == 0 ? OK : MapSystemError(errno);
421 }
422
423 int UDPSocketPosix::SetSendBufferSize(int32_t size) {
424 DCHECK_NE(socket_, kInvalidSocket);
425 DCHECK(CalledOnValidThread());
426 int rv = setsockopt(socket_, SOL_SOCKET, SO_SNDBUF,
427 reinterpret_cast<const char*>(&size), sizeof(size));
428 return rv == 0 ? OK : MapSystemError(errno);
429 }
430
431 int UDPSocketPosix::SetDoNotFragment() {
432 DCHECK_NE(socket_, kInvalidSocket);
433 DCHECK(CalledOnValidThread());
434
435 #if !defined(IP_PMTUDISC_DO)
436 return ERR_NOT_IMPLEMENTED;
437 #else
438 if (addr_family_ == AF_INET6) {
439 int val = IPV6_PMTUDISC_DO;
440 if (setsockopt(socket_, IPPROTO_IPV6, IPV6_MTU_DISCOVER, &val,
441 sizeof(val)) != 0) {
442 return MapSystemError(errno);
443 }
444
445 int v6_only = false;
446 socklen_t v6_only_len = sizeof(v6_only);
447 if (getsockopt(socket_, IPPROTO_IPV6, IPV6_V6ONLY, &v6_only,
448 &v6_only_len) != 0) {
449 return MapSystemError(errno);
450 }
451
452 if (v6_only)
453 return OK;
454 }
455
456 int val = IP_PMTUDISC_DO;
457 int rv = setsockopt(socket_, IPPROTO_IP, IP_MTU_DISCOVER, &val, sizeof(val));
458 return rv == 0 ? OK : MapSystemError(errno);
459 #endif
460 }
461
462 int UDPSocketPosix::AllowAddressReuse() {
463 DCHECK_NE(socket_, kInvalidSocket);
464 DCHECK(CalledOnValidThread());
465 DCHECK(!is_connected());
466 int true_value = 1;
467 int rv = setsockopt(
468 socket_, SOL_SOCKET, SO_REUSEADDR, &true_value, sizeof(true_value));
469 return rv == 0 ? OK : MapSystemError(errno);
470 }
471
472 int UDPSocketPosix::SetBroadcast(bool broadcast) {
473 DCHECK_NE(socket_, kInvalidSocket);
474 DCHECK(CalledOnValidThread());
475 int value = broadcast ? 1 : 0;
476 int rv;
477 #if defined(OS_MACOSX)
478 // SO_REUSEPORT on OSX permits multiple processes to each receive
479 // UDP multicast or broadcast datagrams destined for the bound
480 // port.
481 // This is only being set on OSX because its behavior is platform dependent
482 // and we are playing it safe by only setting it on platforms where things
483 // break.
484 rv = setsockopt(socket_, SOL_SOCKET, SO_REUSEPORT, &value, sizeof(value));
485 if (rv != 0)
486 return MapSystemError(errno);
487 #endif // defined(OS_MACOSX)
488 rv = setsockopt(socket_, SOL_SOCKET, SO_BROADCAST, &value, sizeof(value));
489
490 return rv == 0 ? OK : MapSystemError(errno);
491 }
492
493 void UDPSocketPosix::ReadWatcher::OnFileCanReadWithoutBlocking(int) {
494 TRACE_EVENT0("net",
495 "UDPSocketPosix::ReadWatcher::OnFileCanReadWithoutBlocking");
496 if (!socket_->read_callback_.is_null())
497 socket_->DidCompleteRead();
498 }
499
500 void UDPSocketPosix::WriteWatcher::OnFileCanWriteWithoutBlocking(int) {
501 if (!socket_->write_callback_.is_null())
502 socket_->DidCompleteWrite();
503 }
504
505 void UDPSocketPosix::DoReadCallback(int rv) {
506 DCHECK_NE(rv, ERR_IO_PENDING);
507 DCHECK(!read_callback_.is_null());
508
509 // since Run may result in Read being called, clear read_callback_ up front.
510 CompletionCallback c = read_callback_;
511 read_callback_.Reset();
512 c.Run(rv);
513 }
514
515 void UDPSocketPosix::DoWriteCallback(int rv) {
516 DCHECK_NE(rv, ERR_IO_PENDING);
517 DCHECK(!write_callback_.is_null());
518
519 // since Run may result in Write being called, clear write_callback_ up front.
520 CompletionCallback c = write_callback_;
521 write_callback_.Reset();
522 c.Run(rv);
523 }
524
525 void UDPSocketPosix::DidCompleteRead() {
526 int result =
527 InternalRecvFrom(read_buf_.get(), read_buf_len_, recv_from_address_);
528 if (result != ERR_IO_PENDING) {
529 read_buf_ = NULL;
530 read_buf_len_ = 0;
531 recv_from_address_ = NULL;
532 bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
533 DCHECK(ok);
534 DoReadCallback(result);
535 }
536 }
537
538 void UDPSocketPosix::LogRead(int result,
539 const char* bytes,
540 socklen_t addr_len,
541 const sockaddr* addr) const {
542 if (result < 0) {
543 net_log_.AddEventWithNetErrorCode(NetLogEventType::UDP_RECEIVE_ERROR,
544 result);
545 return;
546 }
547
548 if (net_log_.IsCapturing()) {
549 DCHECK(addr_len > 0);
550 DCHECK(addr);
551
552 IPEndPoint address;
553 bool is_address_valid = address.FromSockAddr(addr, addr_len);
554 net_log_.AddEvent(NetLogEventType::UDP_BYTES_RECEIVED,
555 CreateNetLogUDPDataTranferCallback(
556 result, bytes, is_address_valid ? &address : NULL));
557 }
558
559 NetworkActivityMonitor::GetInstance()->IncrementBytesReceived(result);
560 }
561
562 void UDPSocketPosix::DidCompleteWrite() {
563 int result =
564 InternalSendTo(write_buf_.get(), write_buf_len_, send_to_address_.get());
565
566 if (result != ERR_IO_PENDING) {
567 write_buf_ = NULL;
568 write_buf_len_ = 0;
569 send_to_address_.reset();
570 write_socket_watcher_.StopWatchingFileDescriptor();
571 DoWriteCallback(result);
572 }
573 }
574
575 void UDPSocketPosix::LogWrite(int result,
576 const char* bytes,
577 const IPEndPoint* address) const {
578 if (result < 0) {
579 net_log_.AddEventWithNetErrorCode(NetLogEventType::UDP_SEND_ERROR, result);
580 return;
581 }
582
583 if (net_log_.IsCapturing()) {
584 net_log_.AddEvent(
585 NetLogEventType::UDP_BYTES_SENT,
586 CreateNetLogUDPDataTranferCallback(result, bytes, address));
587 }
588
589 NetworkActivityMonitor::GetInstance()->IncrementBytesSent(result);
590 }
591
592 int UDPSocketPosix::InternalRecvFrom(IOBuffer* buf,
593 int buf_len,
594 IPEndPoint* address) {
595 int bytes_transferred;
596 int flags = 0;
597
598 SockaddrStorage storage;
599
600 bytes_transferred =
601 HANDLE_EINTR(recvfrom(socket_,
602 buf->data(),
603 buf_len,
604 flags,
605 storage.addr,
606 &storage.addr_len));
607 int result;
608 if (bytes_transferred >= 0) {
609 result = bytes_transferred;
610 if (address && !address->FromSockAddr(storage.addr, storage.addr_len))
611 result = ERR_ADDRESS_INVALID;
612 } else {
613 result = MapSystemError(errno);
614 }
615 if (result != ERR_IO_PENDING)
616 LogRead(result, buf->data(), storage.addr_len, storage.addr);
617 return result;
618 }
619
620 int UDPSocketPosix::InternalSendTo(IOBuffer* buf,
621 int buf_len,
622 const IPEndPoint* address) {
623 SockaddrStorage storage;
624 struct sockaddr* addr = storage.addr;
625 if (!address) {
626 addr = NULL;
627 storage.addr_len = 0;
628 } else {
629 if (!address->ToSockAddr(storage.addr, &storage.addr_len)) {
630 int result = ERR_ADDRESS_INVALID;
631 LogWrite(result, NULL, NULL);
632 return result;
633 }
634 }
635
636 int result = HANDLE_EINTR(sendto(socket_,
637 buf->data(),
638 buf_len,
639 0,
640 addr,
641 storage.addr_len));
642 if (result < 0)
643 result = MapSystemError(errno);
644 if (result != ERR_IO_PENDING)
645 LogWrite(result, buf->data(), address);
646 return result;
647 }
648
649 int UDPSocketPosix::SetMulticastOptions() {
650 if (!(socket_options_ & SOCKET_OPTION_MULTICAST_LOOP)) {
651 int rv;
652 if (addr_family_ == AF_INET) {
653 u_char loop = 0;
654 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_LOOP,
655 &loop, sizeof(loop));
656 } else {
657 u_int loop = 0;
658 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_LOOP,
659 &loop, sizeof(loop));
660 }
661 if (rv < 0)
662 return MapSystemError(errno);
663 }
664 if (multicast_time_to_live_ != IP_DEFAULT_MULTICAST_TTL) {
665 int rv;
666 if (addr_family_ == AF_INET) {
667 u_char ttl = multicast_time_to_live_;
668 rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_TTL,
669 &ttl, sizeof(ttl));
670 } else {
671 // Signed integer. -1 to use route default.
672 int ttl = multicast_time_to_live_;
673 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_HOPS,
674 &ttl, sizeof(ttl));
675 }
676 if (rv < 0)
677 return MapSystemError(errno);
678 }
679 if (multicast_interface_ != 0) {
680 switch (addr_family_) {
681 case AF_INET: {
682 #if !defined(OS_MACOSX)
683 ip_mreqn mreq;
684 mreq.imr_ifindex = multicast_interface_;
685 mreq.imr_address.s_addr = htonl(INADDR_ANY);
686 #else
687 ip_mreq mreq;
688 int error = GetIPv4AddressFromIndex(socket_, multicast_interface_,
689 &mreq.imr_interface.s_addr);
690 if (error != OK)
691 return error;
692 #endif
693 int rv = setsockopt(socket_, IPPROTO_IP, IP_MULTICAST_IF,
694 reinterpret_cast<const char*>(&mreq), sizeof(mreq));
695 if (rv)
696 return MapSystemError(errno);
697 break;
698 }
699 case AF_INET6: {
700 uint32_t interface_index = multicast_interface_;
701 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_MULTICAST_IF,
702 reinterpret_cast<const char*>(&interface_index),
703 sizeof(interface_index));
704 if (rv)
705 return MapSystemError(errno);
706 break;
707 }
708 default:
709 NOTREACHED() << "Invalid address family";
710 return ERR_ADDRESS_INVALID;
711 }
712 }
713 return OK;
714 }
715
716 int UDPSocketPosix::DoBind(const IPEndPoint& address) {
717 SockaddrStorage storage;
718 if (!address.ToSockAddr(storage.addr, &storage.addr_len))
719 return ERR_ADDRESS_INVALID;
720 int rv = bind(socket_, storage.addr, storage.addr_len);
721 if (rv == 0)
722 return OK;
723 int last_error = errno;
724 UMA_HISTOGRAM_SPARSE_SLOWLY("Net.UdpSocketBindErrorFromPosix", last_error);
725 #if defined(OS_CHROMEOS)
726 if (last_error == EINVAL)
727 return ERR_ADDRESS_IN_USE;
728 #elif defined(OS_MACOSX)
729 if (last_error == EADDRNOTAVAIL)
730 return ERR_ADDRESS_IN_USE;
731 #endif
732 return MapSystemError(last_error);
733 }
734
735 int UDPSocketPosix::RandomBind(const IPAddress& address) {
736 DCHECK(bind_type_ == DatagramSocket::RANDOM_BIND && !rand_int_cb_.is_null());
737
738 for (int i = 0; i < kBindRetries; ++i) {
739 int rv = DoBind(IPEndPoint(address,
740 rand_int_cb_.Run(kPortStart, kPortEnd)));
741 if (rv != ERR_ADDRESS_IN_USE)
742 return rv;
743 }
744 return DoBind(IPEndPoint(address, 0));
745 }
746
747 int UDPSocketPosix::JoinGroup(const IPAddress& group_address) const {
748 DCHECK(CalledOnValidThread());
749 if (!is_connected())
750 return ERR_SOCKET_NOT_CONNECTED;
751
752 switch (group_address.size()) {
753 case IPAddress::kIPv4AddressSize: {
754 if (addr_family_ != AF_INET)
755 return ERR_ADDRESS_INVALID;
756
757 #if !defined(OS_MACOSX)
758 ip_mreqn mreq;
759 mreq.imr_ifindex = multicast_interface_;
760 mreq.imr_address.s_addr = htonl(INADDR_ANY);
761 #else
762 ip_mreq mreq;
763 int error = GetIPv4AddressFromIndex(socket_, multicast_interface_,
764 &mreq.imr_interface.s_addr);
765 if (error != OK)
766 return error;
767 #endif
768 memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
769 IPAddress::kIPv4AddressSize);
770 int rv = setsockopt(socket_, IPPROTO_IP, IP_ADD_MEMBERSHIP,
771 &mreq, sizeof(mreq));
772 if (rv < 0)
773 return MapSystemError(errno);
774 return OK;
775 }
776 case IPAddress::kIPv6AddressSize: {
777 if (addr_family_ != AF_INET6)
778 return ERR_ADDRESS_INVALID;
779 ipv6_mreq mreq;
780 mreq.ipv6mr_interface = multicast_interface_;
781 memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
782 IPAddress::kIPv6AddressSize);
783 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_JOIN_GROUP,
784 &mreq, sizeof(mreq));
785 if (rv < 0)
786 return MapSystemError(errno);
787 return OK;
788 }
789 default:
790 NOTREACHED() << "Invalid address family";
791 return ERR_ADDRESS_INVALID;
792 }
793 }
794
795 int UDPSocketPosix::LeaveGroup(const IPAddress& group_address) const {
796 DCHECK(CalledOnValidThread());
797
798 if (!is_connected())
799 return ERR_SOCKET_NOT_CONNECTED;
800
801 switch (group_address.size()) {
802 case IPAddress::kIPv4AddressSize: {
803 if (addr_family_ != AF_INET)
804 return ERR_ADDRESS_INVALID;
805 ip_mreq mreq;
806 mreq.imr_interface.s_addr = INADDR_ANY;
807 memcpy(&mreq.imr_multiaddr, group_address.bytes().data(),
808 IPAddress::kIPv4AddressSize);
809 int rv = setsockopt(socket_, IPPROTO_IP, IP_DROP_MEMBERSHIP,
810 &mreq, sizeof(mreq));
811 if (rv < 0)
812 return MapSystemError(errno);
813 return OK;
814 }
815 case IPAddress::kIPv6AddressSize: {
816 if (addr_family_ != AF_INET6)
817 return ERR_ADDRESS_INVALID;
818 ipv6_mreq mreq;
819 mreq.ipv6mr_interface = 0; // 0 indicates default multicast interface.
820 memcpy(&mreq.ipv6mr_multiaddr, group_address.bytes().data(),
821 IPAddress::kIPv6AddressSize);
822 int rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_LEAVE_GROUP,
823 &mreq, sizeof(mreq));
824 if (rv < 0)
825 return MapSystemError(errno);
826 return OK;
827 }
828 default:
829 NOTREACHED() << "Invalid address family";
830 return ERR_ADDRESS_INVALID;
831 }
832 }
833
834 int UDPSocketPosix::SetMulticastInterface(uint32_t interface_index) {
835 DCHECK(CalledOnValidThread());
836 if (is_connected())
837 return ERR_SOCKET_IS_CONNECTED;
838 multicast_interface_ = interface_index;
839 return OK;
840 }
841
842 int UDPSocketPosix::SetMulticastTimeToLive(int time_to_live) {
843 DCHECK(CalledOnValidThread());
844 if (is_connected())
845 return ERR_SOCKET_IS_CONNECTED;
846
847 if (time_to_live < 0 || time_to_live > 255)
848 return ERR_INVALID_ARGUMENT;
849 multicast_time_to_live_ = time_to_live;
850 return OK;
851 }
852
853 int UDPSocketPosix::SetMulticastLoopbackMode(bool loopback) {
854 DCHECK(CalledOnValidThread());
855 if (is_connected())
856 return ERR_SOCKET_IS_CONNECTED;
857
858 if (loopback)
859 socket_options_ |= SOCKET_OPTION_MULTICAST_LOOP;
860 else
861 socket_options_ &= ~SOCKET_OPTION_MULTICAST_LOOP;
862 return OK;
863 }
864
865 int UDPSocketPosix::SetDiffServCodePoint(DiffServCodePoint dscp) {
866 if (dscp == DSCP_NO_CHANGE) {
867 return OK;
868 }
869 int rv;
870 int dscp_and_ecn = dscp << 2;
871 if (addr_family_ == AF_INET) {
872 rv = setsockopt(socket_, IPPROTO_IP, IP_TOS,
873 &dscp_and_ecn, sizeof(dscp_and_ecn));
874 } else {
875 rv = setsockopt(socket_, IPPROTO_IPV6, IPV6_TCLASS,
876 &dscp_and_ecn, sizeof(dscp_and_ecn));
877 }
878 if (rv < 0)
879 return MapSystemError(errno);
880
881 return OK;
882 }
883
884 void UDPSocketPosix::DetachFromThread() {
885 base::NonThreadSafe::DetachFromThread();
886 }
887
888 } // namespace net
OLDNEW
« no previous file with comments | « net/udp/udp_socket_posix.h ('k') | net/udp/udp_socket_unittest.cc » ('j') | no next file with comments »

Powered by Google App Engine
This is Rietveld 408576698