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)
42     : fd_(fd), am_(am), watching_(false) {
43   int flags = fcntl(fd, F_GETFL);
44   fcntl(fd, F_SETFL, flags | O_NONBLOCK);
45 
46   flags = fcntl(fd, F_GETFD);
47   fcntl(fd, F_SETFD, flags | FD_CLOEXEC);
48 
49 #ifdef SO_NOSIGPIPE
50   // Disable SIGPIPE generation on Darwin.
51   // When writing to a broken pipe, send() will return -1 and
52   // set errno to EPIPE.
53   flags = 1;
54   setsockopt(fd, SOL_SOCKET, SO_NOSIGPIPE, (const char*)&flags, sizeof(flags));
55 #endif
56 }
57 
PosixAsyncSocket(PosixAsyncSocket && other)58 PosixAsyncSocket::PosixAsyncSocket(PosixAsyncSocket&& other) {
59   fd_ = other.fd_;
60   watching_ = other.watching_.load();
61   am_ = other.am_;
62 
63   other.fd_ = -1;
64   other.watching_ = false;
65 }
~PosixAsyncSocket()66 PosixAsyncSocket::~PosixAsyncSocket() { Close(); }
67 
Recv(uint8_t * buffer,uint64_t bufferSize)68 ssize_t PosixAsyncSocket::Recv(uint8_t* buffer, uint64_t bufferSize) {
69   if (fd_ == -1) {
70     // Socket was closed locally.
71     return 0;
72   }
73 
74   errno = 0;
75   ssize_t res = 0;
76   REPEAT_UNTIL_NO_INTR(res = read(fd_, buffer, bufferSize));
77 
78   if (res < 0) {
79     DD("Recv < 0: {} ({})", strerror(errno), fd_);
80   }
81   DD("{} bytes ({})", res, fd_);
82   return res;
83 };
84 
Send(const uint8_t * buffer,uint64_t bufferSize)85 ssize_t PosixAsyncSocket::Send(const uint8_t* buffer, uint64_t bufferSize) {
86   errno = 0;
87   ssize_t res = 0;
88 #ifdef MSG_NOSIGNAL
89   // Prevent SIGPIPE generation on Linux when writing to a broken pipe.
90   // ::send() will return -1/EPIPE instead.
91   const int sendFlags = MSG_NOSIGNAL;
92 #else
93   // For Darwin, this is handled by setting SO_NOSIGPIPE when creating
94   // the socket.
95   const int sendFlags = 0;
96 #endif
97 
98   REPEAT_UNTIL_NO_INTR(res = send(fd_, buffer, bufferSize, sendFlags));
99 
100   DD("{} bytes ({})", res, fd_);
101   return res;
102 }
103 
Connected()104 bool PosixAsyncSocket::Connected() {
105   if (fd_ == -1) {
106     return false;
107   }
108   char buf;
109   if (recv(fd_, &buf, 1, MSG_PEEK | MSG_DONTWAIT) != 1) {
110     DD("Recv not 1, could be connected: {} ({})", strerror(errno), fd_);
111     return errno == EAGAIN || errno == EWOULDBLOCK;
112   }
113 
114   // We saw a byte in the queue, we are likely connected.
115   return true;
116 }
117 
Close()118 void PosixAsyncSocket::Close() {
119   if (fd_ == -1) {
120     return;
121   }
122 
123   StopWatching();
124 
125   // Clear out error
126   int error_code = 0;
127   socklen_t error_code_size = sizeof(error_code);
128   getsockopt(fd_, SOL_SOCKET, SO_ERROR, reinterpret_cast<void*>(&error_code),
129              &error_code_size);
130 
131   // shutdown sockets if possible,
132   REPEAT_UNTIL_NO_INTR(shutdown(fd_, SHUT_RDWR));
133 
134   error_code = ::close(fd_);
135   if (error_code == -1) {
136     INFO("Failed to close: {} ({})", strerror(errno), fd_);
137   }
138   INFO("({})", fd_);
139   fd_ = -1;
140 }
141 
WatchForNonBlockingRead(const ReadCallback & on_read_ready_callback)142 bool PosixAsyncSocket::WatchForNonBlockingRead(
143     const ReadCallback& on_read_ready_callback) {
144   bool expected = false;
145   if (watching_.compare_exchange_strong(expected, true)) {
146     return am_->WatchFdForNonBlockingReads(
147                fd_, [on_read_ready_callback, this](int /* fd */) {
148                  on_read_ready_callback(this);
149                }) == 0;
150   }
151   return false;
152 }
153 
StopWatching()154 void PosixAsyncSocket::StopWatching() {
155   bool expected = true;
156   if (watching_.compare_exchange_strong(expected, false)) {
157     am_->StopWatchingFileDescriptor(fd_);
158   }
159 }
160 }  // namespace net
161 }  // namespace android
162