1 // Copyright (C) 2021 The Android Open Source Project
2 //
3 // Licensed under the Apache License, Version 2.0 (the "License");
4 // you may not use this file except in compliance with the License.
5 // You may obtain a copy of the License at
6 //
7 // http://www.apache.org/licenses/LICENSE-2.0
8 //
9 // Unless required by applicable law or agreed to in writing, software
10 // distributed under the License is distributed on an "AS IS" BASIS,
11 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 // See the License for the specific language governing permissions and
13 // limitations under the License.
14 #include "net/posix/posix_async_socket.h"
15 
16 #include <errno.h>       // for errno
17 #include <fcntl.h>       // for fcntl, FD_CLOEXEC, F_GETFL
18 #include <string.h>      // for strerror
19 #include <sys/socket.h>  // for getsockopt, send, MSG_NOSIGNAL
20 #include <unistd.h>      // for close, read
21 
22 #include <functional>  // for __base
23 
24 #include "log.h"
25 #include "model/setup/async_manager.h"  // for AsyncManager
26 
27 #ifdef _WIN32
28 #include "msvc-posix.h"
29 #endif
30 
31 /* set  for very verbose debugging */
32 #ifdef NDEBUG
33 #define DD(...) (void)0
34 #else
35 #define DD(...) INFO(__VA_ARGS__)
36 #endif
37 
38 namespace android {
39 namespace net {
40 
PosixAsyncSocket(int fd,AsyncManager * am)41 PosixAsyncSocket::PosixAsyncSocket(int fd, AsyncManager* am) : fd_(fd), am_(am), watching_(false) {
42   int flags = fcntl(fd, F_GETFL);
43   fcntl(fd, F_SETFL, flags | O_NONBLOCK);
44 
45   flags = fcntl(fd, F_GETFD);
46   fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
47 
48 #ifdef SO_NOSIGPIPE
49   // Disable SIGPIPE generation on Darwin.
50   // When writing to a broken pipe, send() will return -1 and
51   // set errno to EPIPE.
52   flags = 1;
53   setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&flags, sizeof(flags));
54 #endif
55 }
56 
PosixAsyncSocket(PosixAsyncSocket && other)57 PosixAsyncSocket::PosixAsyncSocket(PosixAsyncSocket&& other) {
58   fd_ = other.fd_;
59   watching_ = other.watching_.load();
60   am_ = other.am_;
61 
62   other.fd_ = -1;
63   other.watching_ = false;
64 }
~PosixAsyncSocket()65 PosixAsyncSocket::~PosixAsyncSocket() { Close(); }
66 
Recv(uint8_t * buffer,uint64_t bufferSize)67 ssize_t PosixAsyncSocket::Recv(uint8_t* buffer, uint64_t bufferSize) {
68   if (fd_ == -1) {
69     // Socket was closed locally.
70     return 0;
71   }
72 
73   errno = 0;
74   ssize_t res = 0;
75   REPEAT_UNTIL_NO_INTR(res = read(fd_, buffer, bufferSize));
76 
77   if (res < 0) {
78     DD("Recv < 0: {} ({})", strerror(errno), fd_);
79   }
80   DD("{} bytes ({})", res, fd_);
81   return res;
82 }
83 
Send(const uint8_t * buffer,uint64_t bufferSize)84 ssize_t PosixAsyncSocket::Send(const uint8_t* buffer, uint64_t bufferSize) {
85   errno = 0;
86   ssize_t res = 0;
87 #ifdef MSG_NOSIGNAL
88   // Prevent SIGPIPE generation on Linux when writing to a broken pipe.
89   // ::send() will return -1/EPIPE instead.
90   const int sendFlags = MSG_NOSIGNAL;
91 #else
92   // For Darwin, this is handled by setting SO_NOSIGPIPE when creating
93   // the socket.
94   const int sendFlags = 0;
95 #endif
96 
97   REPEAT_UNTIL_NO_INTR(res = send(fd_, buffer, bufferSize, sendFlags));
98 
99   DD("{} bytes ({})", res, fd_);
100   return res;
101 }
102 
Connected()103 bool PosixAsyncSocket::Connected() {
104   if (fd_ == -1) {
105     return false;
106   }
107   char buf;
108   if (recv(fd_, &buf, 1, MSG_PEEK | MSG_DONTWAIT) != 1) {
109     DD("Recv not 1, could be connected: {} ({})", strerror(errno), fd_);
110     return errno == EAGAIN || errno == EWOULDBLOCK;
111   }
112 
113   // We saw a byte in the queue, we are likely connected.
114   return true;
115 }
116 
Close()117 void PosixAsyncSocket::Close() {
118   if (fd_ == -1) {
119     return;
120   }
121 
122   StopWatching();
123 
124   // Clear out error
125   int error_code = 0;
126   socklen_t error_code_size = sizeof(error_code);
127   getsockopt(fd_, SOL_SOCKET, SO_ERROR, reinterpret_cast<void*>(&error_code), &error_code_size);
128 
129   // shutdown sockets if possible,
130   REPEAT_UNTIL_NO_INTR(shutdown(fd_, SHUT_RDWR));
131 
132   error_code = ::close(fd_);
133   if (error_code == -1) {
134     INFO("Failed to close: {} ({})", strerror(errno), fd_);
135   }
136   INFO("({})", fd_);
137   fd_ = -1;
138 }
139 
WatchForNonBlockingRead(const ReadCallback & on_read_ready_callback)140 bool PosixAsyncSocket::WatchForNonBlockingRead(const ReadCallback& on_read_ready_callback) {
141   bool expected = false;
142   if (watching_.compare_exchange_strong(expected, true)) {
143     return am_->WatchFdForNonBlockingReads(fd_, [on_read_ready_callback, this](int /* fd */) {
144       on_read_ready_callback(this);
145     }) == 0;
146   }
147   return false;
148 }
149 
StopWatching()150 void PosixAsyncSocket::StopWatching() {
151   bool expected = true;
152   if (watching_.compare_exchange_strong(expected, false)) {
153     am_->StopWatchingFileDescriptor(fd_);
154   }
155 }
156 }  // namespace net
157 }  // namespace android
158