blob: fea1792ea3f5fa4d1aba9d34cac1b07248d4d7d8 [file] [log] [blame]
Garrick Evans3cbac7c2019-04-18 15:31:31 +09001// Copyright 2019 The Chromium OS 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
Garrick Evans3388a032020-03-24 11:25:55 +09005#include "patchpanel/socket.h"
Garrick Evans3cbac7c2019-04-18 15:31:31 +09006
7#include <arpa/inet.h>
8#include <errno.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +09009#include <net/if.h>
10#include <string.h>
11#include <sys/ioctl.h>
Garrick Evans3cbac7c2019-04-18 15:31:31 +090012#include <unistd.h>
13
14#include <utility>
15
16#include <base/logging.h>
17#include <base/memory/ptr_util.h>
18
Garrick Evans3388a032020-03-24 11:25:55 +090019#include "patchpanel/net_util.h"
Hugo Benichidcc32392020-02-27 09:14:40 +090020
Garrick Evans3388a032020-03-24 11:25:55 +090021namespace patchpanel {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090022namespace {
23
24bool WouldBlock() {
25 return errno == EAGAIN || errno == EWOULDBLOCK;
26}
Garrick Evans3cbac7c2019-04-18 15:31:31 +090027} // namespace
28
Hugo Benichida86b2b2021-08-19 14:08:05 +090029Socket::Socket(int family, int type) : fd_(socket(family, type, 0)) {}
Garrick Evans3cbac7c2019-04-18 15:31:31 +090030
Hugo Benichida86b2b2021-08-19 14:08:05 +090031Socket::Socket(base::ScopedFD fd) : fd_(std::move(fd)) {}
Garrick Evans3cbac7c2019-04-18 15:31:31 +090032
Garrick Evansfa872f62019-05-28 16:49:25 +090033bool Socket::Bind(const struct sockaddr* addr, socklen_t addrlen) {
Hugo Benichida86b2b2021-08-19 14:08:05 +090034 return bind(fd_.get(), addr, addrlen) == 0;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090035}
36
Garrick Evansfa872f62019-05-28 16:49:25 +090037bool Socket::Connect(const struct sockaddr* addr, socklen_t addrlen) {
Hugo Benichida86b2b2021-08-19 14:08:05 +090038 return connect(fd_.get(), addr, addrlen) == 0;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090039}
40
41bool Socket::Listen(int backlog) const {
Hugo Benichida86b2b2021-08-19 14:08:05 +090042 return listen(fd_.get(), backlog) == 0;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090043}
44
45std::unique_ptr<Socket> Socket::Accept(struct sockaddr* addr,
46 socklen_t* addrlen) const {
47 base::ScopedFD fd(accept(fd_.get(), addr, addrlen));
48 if (!fd.is_valid()) {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090049 return nullptr;
50 }
51 return std::make_unique<Socket>(std::move(fd));
52}
53
Garrick Evans1cce71a2019-06-21 10:43:14 +090054ssize_t Socket::SendTo(const void* data,
55 size_t len,
56 const struct sockaddr* addr,
57 socklen_t addrlen) {
Garrick Evans3cbac7c2019-04-18 15:31:31 +090058 if (!fd_.is_valid()) {
59 return -1;
60 }
Garrick Evans1cce71a2019-06-21 10:43:14 +090061 if (!addr) {
62 addrlen = 0;
63 } else if (addrlen == 0) {
64 addrlen = sizeof(*addr);
65 }
66
Garrick Evans3cbac7c2019-04-18 15:31:31 +090067 ssize_t bytes = sendto(fd_.get(), data, len, MSG_NOSIGNAL, addr, addrlen);
68 if (bytes >= 0)
69 return bytes;
70
71 if (WouldBlock())
72 return 0;
73
Garrick Evans3cbac7c2019-04-18 15:31:31 +090074 return bytes;
75}
76
77ssize_t Socket::RecvFrom(void* data,
78 size_t len,
79 struct sockaddr* addr,
80 socklen_t addrlen) {
81 socklen_t recvlen = addrlen;
82 ssize_t bytes = recvfrom(fd_.get(), data, len, 0, addr, &recvlen);
83 if (bytes >= 0) {
84 if (recvlen != addrlen)
Hugo Benichida86b2b2021-08-19 14:08:05 +090085 LOG(WARNING) << "recvfrom failed: unexpected src addr length " << recvlen;
Garrick Evans3cbac7c2019-04-18 15:31:31 +090086 return bytes;
87 }
88
89 if (WouldBlock())
90 return 0;
91
Garrick Evans3cbac7c2019-04-18 15:31:31 +090092 return bytes;
93}
94
95std::ostream& operator<<(std::ostream& stream, const Socket& socket) {
96 stream << "{fd: " << socket.fd() << "}";
97 return stream;
98}
99
Garrick Evans3388a032020-03-24 11:25:55 +0900100} // namespace patchpanel