PageRenderTime 64ms CodeModel.GetById 37ms RepoModel.GetById 0ms app.codeStats 0ms

/net/socket/socket_posix.cc

https://gitlab.com/hkratz/chromium
C++ | 487 lines | 379 code | 85 blank | 23 comment | 72 complexity | 031c9cd126fd6000da684565ec658edc MD5 | raw file
  1. // Copyright 2014 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. #include "net/socket/socket_posix.h"
  5. #include <errno.h>
  6. #include <netinet/in.h>
  7. #include <sys/socket.h>
  8. #include <utility>
  9. #include "base/callback_helpers.h"
  10. #include "base/files/file_util.h"
  11. #include "base/logging.h"
  12. #include "base/posix/eintr_wrapper.h"
  13. #include "net/base/io_buffer.h"
  14. #include "net/base/ip_endpoint.h"
  15. #include "net/base/net_errors.h"
  16. #include "net/base/net_util.h"
  17. namespace net {
  18. namespace {
  19. int MapAcceptError(int os_error) {
  20. switch (os_error) {
  21. // If the client aborts the connection before the server calls accept,
  22. // POSIX specifies accept should fail with ECONNABORTED. The server can
  23. // ignore the error and just call accept again, so we map the error to
  24. // ERR_IO_PENDING. See UNIX Network Programming, Vol. 1, 3rd Ed., Sec.
  25. // 5.11, "Connection Abort before accept Returns".
  26. case ECONNABORTED:
  27. return ERR_IO_PENDING;
  28. default:
  29. return MapSystemError(os_error);
  30. }
  31. }
  32. int MapConnectError(int os_error) {
  33. switch (os_error) {
  34. case EINPROGRESS:
  35. return ERR_IO_PENDING;
  36. case EACCES:
  37. return ERR_NETWORK_ACCESS_DENIED;
  38. case ETIMEDOUT:
  39. return ERR_CONNECTION_TIMED_OUT;
  40. default: {
  41. int net_error = MapSystemError(os_error);
  42. if (net_error == ERR_FAILED)
  43. return ERR_CONNECTION_FAILED; // More specific than ERR_FAILED.
  44. return net_error;
  45. }
  46. }
  47. }
  48. } // namespace
  49. SocketPosix::SocketPosix()
  50. : socket_fd_(kInvalidSocket),
  51. read_buf_len_(0),
  52. write_buf_len_(0),
  53. waiting_connect_(false) {}
  54. SocketPosix::~SocketPosix() {
  55. Close();
  56. }
  57. int SocketPosix::Open(int address_family) {
  58. DCHECK(thread_checker_.CalledOnValidThread());
  59. DCHECK_EQ(kInvalidSocket, socket_fd_);
  60. DCHECK(address_family == AF_INET ||
  61. address_family == AF_INET6 ||
  62. address_family == AF_UNIX);
  63. socket_fd_ = CreatePlatformSocket(
  64. address_family,
  65. SOCK_STREAM,
  66. address_family == AF_UNIX ? 0 : IPPROTO_TCP);
  67. if (socket_fd_ < 0) {
  68. PLOG(ERROR) << "CreatePlatformSocket() returned an error, errno=" << errno;
  69. return MapSystemError(errno);
  70. }
  71. if (!base::SetNonBlocking(socket_fd_)) {
  72. int rv = MapSystemError(errno);
  73. Close();
  74. return rv;
  75. }
  76. return OK;
  77. }
  78. int SocketPosix::AdoptConnectedSocket(SocketDescriptor socket,
  79. const SockaddrStorage& address) {
  80. DCHECK(thread_checker_.CalledOnValidThread());
  81. DCHECK_EQ(kInvalidSocket, socket_fd_);
  82. socket_fd_ = socket;
  83. if (!base::SetNonBlocking(socket_fd_)) {
  84. int rv = MapSystemError(errno);
  85. Close();
  86. return rv;
  87. }
  88. SetPeerAddress(address);
  89. return OK;
  90. }
  91. SocketDescriptor SocketPosix::ReleaseConnectedSocket() {
  92. StopWatchingAndCleanUp();
  93. SocketDescriptor socket_fd = socket_fd_;
  94. socket_fd_ = kInvalidSocket;
  95. return socket_fd;
  96. }
  97. int SocketPosix::Bind(const SockaddrStorage& address) {
  98. DCHECK(thread_checker_.CalledOnValidThread());
  99. DCHECK_NE(kInvalidSocket, socket_fd_);
  100. int rv = bind(socket_fd_, address.addr, address.addr_len);
  101. if (rv < 0) {
  102. PLOG(ERROR) << "bind() returned an error, errno=" << errno;
  103. return MapSystemError(errno);
  104. }
  105. return OK;
  106. }
  107. int SocketPosix::Listen(int backlog) {
  108. DCHECK(thread_checker_.CalledOnValidThread());
  109. DCHECK_NE(kInvalidSocket, socket_fd_);
  110. DCHECK_LT(0, backlog);
  111. int rv = listen(socket_fd_, backlog);
  112. if (rv < 0) {
  113. PLOG(ERROR) << "listen() returned an error, errno=" << errno;
  114. return MapSystemError(errno);
  115. }
  116. return OK;
  117. }
  118. int SocketPosix::Accept(scoped_ptr<SocketPosix>* socket,
  119. const CompletionCallback& callback) {
  120. DCHECK(thread_checker_.CalledOnValidThread());
  121. DCHECK_NE(kInvalidSocket, socket_fd_);
  122. DCHECK(accept_callback_.is_null());
  123. DCHECK(socket);
  124. DCHECK(!callback.is_null());
  125. int rv = DoAccept(socket);
  126. if (rv != ERR_IO_PENDING)
  127. return rv;
  128. if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
  129. socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
  130. &accept_socket_watcher_, this)) {
  131. PLOG(ERROR) << "WatchFileDescriptor failed on accept, errno " << errno;
  132. return MapSystemError(errno);
  133. }
  134. accept_socket_ = socket;
  135. accept_callback_ = callback;
  136. return ERR_IO_PENDING;
  137. }
  138. int SocketPosix::Connect(const SockaddrStorage& address,
  139. const CompletionCallback& callback) {
  140. DCHECK(thread_checker_.CalledOnValidThread());
  141. DCHECK_NE(kInvalidSocket, socket_fd_);
  142. DCHECK(!waiting_connect_);
  143. DCHECK(!callback.is_null());
  144. SetPeerAddress(address);
  145. int rv = DoConnect();
  146. if (rv != ERR_IO_PENDING)
  147. return rv;
  148. if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
  149. socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
  150. &write_socket_watcher_, this)) {
  151. PLOG(ERROR) << "WatchFileDescriptor failed on connect, errno " << errno;
  152. return MapSystemError(errno);
  153. }
  154. write_callback_ = callback;
  155. waiting_connect_ = true;
  156. return ERR_IO_PENDING;
  157. }
  158. bool SocketPosix::IsConnected() const {
  159. DCHECK(thread_checker_.CalledOnValidThread());
  160. if (socket_fd_ == kInvalidSocket || waiting_connect_)
  161. return false;
  162. // Checks if connection is alive.
  163. char c;
  164. int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
  165. if (rv == 0)
  166. return false;
  167. if (rv == -1 && errno != EAGAIN && errno != EWOULDBLOCK)
  168. return false;
  169. return true;
  170. }
  171. bool SocketPosix::IsConnectedAndIdle() const {
  172. DCHECK(thread_checker_.CalledOnValidThread());
  173. if (socket_fd_ == kInvalidSocket || waiting_connect_)
  174. return false;
  175. // Check if connection is alive and we haven't received any data
  176. // unexpectedly.
  177. char c;
  178. int rv = HANDLE_EINTR(recv(socket_fd_, &c, 1, MSG_PEEK));
  179. if (rv >= 0)
  180. return false;
  181. if (errno != EAGAIN && errno != EWOULDBLOCK)
  182. return false;
  183. return true;
  184. }
  185. int SocketPosix::Read(IOBuffer* buf,
  186. int buf_len,
  187. const CompletionCallback& callback) {
  188. DCHECK(thread_checker_.CalledOnValidThread());
  189. DCHECK_NE(kInvalidSocket, socket_fd_);
  190. DCHECK(!waiting_connect_);
  191. CHECK(read_callback_.is_null());
  192. // Synchronous operation not supported
  193. DCHECK(!callback.is_null());
  194. DCHECK_LT(0, buf_len);
  195. int rv = DoRead(buf, buf_len);
  196. if (rv != ERR_IO_PENDING)
  197. return rv;
  198. if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
  199. socket_fd_, true, base::MessageLoopForIO::WATCH_READ,
  200. &read_socket_watcher_, this)) {
  201. PLOG(ERROR) << "WatchFileDescriptor failed on read, errno " << errno;
  202. return MapSystemError(errno);
  203. }
  204. read_buf_ = buf;
  205. read_buf_len_ = buf_len;
  206. read_callback_ = callback;
  207. return ERR_IO_PENDING;
  208. }
  209. int SocketPosix::Write(IOBuffer* buf,
  210. int buf_len,
  211. const CompletionCallback& callback) {
  212. DCHECK(thread_checker_.CalledOnValidThread());
  213. DCHECK_NE(kInvalidSocket, socket_fd_);
  214. DCHECK(!waiting_connect_);
  215. CHECK(write_callback_.is_null());
  216. // Synchronous operation not supported
  217. DCHECK(!callback.is_null());
  218. DCHECK_LT(0, buf_len);
  219. int rv = DoWrite(buf, buf_len);
  220. if (rv == ERR_IO_PENDING)
  221. rv = WaitForWrite(buf, buf_len, callback);
  222. return rv;
  223. }
  224. int SocketPosix::WaitForWrite(IOBuffer* buf,
  225. int buf_len,
  226. const CompletionCallback& callback) {
  227. DCHECK(thread_checker_.CalledOnValidThread());
  228. DCHECK_NE(kInvalidSocket, socket_fd_);
  229. DCHECK(write_callback_.is_null());
  230. // Synchronous operation not supported
  231. DCHECK(!callback.is_null());
  232. DCHECK_LT(0, buf_len);
  233. if (!base::MessageLoopForIO::current()->WatchFileDescriptor(
  234. socket_fd_, true, base::MessageLoopForIO::WATCH_WRITE,
  235. &write_socket_watcher_, this)) {
  236. PLOG(ERROR) << "WatchFileDescriptor failed on write, errno " << errno;
  237. return MapSystemError(errno);
  238. }
  239. write_buf_ = buf;
  240. write_buf_len_ = buf_len;
  241. write_callback_ = callback;
  242. return ERR_IO_PENDING;
  243. }
  244. int SocketPosix::GetLocalAddress(SockaddrStorage* address) const {
  245. DCHECK(thread_checker_.CalledOnValidThread());
  246. DCHECK(address);
  247. if (getsockname(socket_fd_, address->addr, &address->addr_len) < 0)
  248. return MapSystemError(errno);
  249. return OK;
  250. }
  251. int SocketPosix::GetPeerAddress(SockaddrStorage* address) const {
  252. DCHECK(thread_checker_.CalledOnValidThread());
  253. DCHECK(address);
  254. if (!HasPeerAddress())
  255. return ERR_SOCKET_NOT_CONNECTED;
  256. *address = *peer_address_;
  257. return OK;
  258. }
  259. void SocketPosix::SetPeerAddress(const SockaddrStorage& address) {
  260. DCHECK(thread_checker_.CalledOnValidThread());
  261. // |peer_address_| will be non-NULL if Connect() has been called. Unless
  262. // Close() is called to reset the internal state, a second call to Connect()
  263. // is not allowed.
  264. // Please note that we don't allow a second Connect() even if the previous
  265. // Connect() has failed. Connecting the same |socket_| again after a
  266. // connection attempt failed results in unspecified behavior according to
  267. // POSIX.
  268. DCHECK(!peer_address_);
  269. peer_address_.reset(new SockaddrStorage(address));
  270. }
  271. bool SocketPosix::HasPeerAddress() const {
  272. DCHECK(thread_checker_.CalledOnValidThread());
  273. return peer_address_ != NULL;
  274. }
  275. void SocketPosix::Close() {
  276. DCHECK(thread_checker_.CalledOnValidThread());
  277. StopWatchingAndCleanUp();
  278. if (socket_fd_ != kInvalidSocket) {
  279. if (IGNORE_EINTR(close(socket_fd_)) < 0)
  280. PLOG(ERROR) << "close() returned an error, errno=" << errno;
  281. socket_fd_ = kInvalidSocket;
  282. }
  283. }
  284. void SocketPosix::DetachFromThread() {
  285. thread_checker_.DetachFromThread();
  286. }
  287. void SocketPosix::OnFileCanReadWithoutBlocking(int fd) {
  288. DCHECK(!accept_callback_.is_null() || !read_callback_.is_null());
  289. if (!accept_callback_.is_null()) {
  290. AcceptCompleted();
  291. } else { // !read_callback_.is_null()
  292. ReadCompleted();
  293. }
  294. }
  295. void SocketPosix::OnFileCanWriteWithoutBlocking(int fd) {
  296. DCHECK(!write_callback_.is_null());
  297. if (waiting_connect_) {
  298. ConnectCompleted();
  299. } else {
  300. WriteCompleted();
  301. }
  302. }
  303. int SocketPosix::DoAccept(scoped_ptr<SocketPosix>* socket) {
  304. SockaddrStorage new_peer_address;
  305. int new_socket = HANDLE_EINTR(accept(socket_fd_,
  306. new_peer_address.addr,
  307. &new_peer_address.addr_len));
  308. if (new_socket < 0)
  309. return MapAcceptError(errno);
  310. scoped_ptr<SocketPosix> accepted_socket(new SocketPosix);
  311. int rv = accepted_socket->AdoptConnectedSocket(new_socket, new_peer_address);
  312. if (rv != OK)
  313. return rv;
  314. *socket = std::move(accepted_socket);
  315. return OK;
  316. }
  317. void SocketPosix::AcceptCompleted() {
  318. DCHECK(accept_socket_);
  319. int rv = DoAccept(accept_socket_);
  320. if (rv == ERR_IO_PENDING)
  321. return;
  322. bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
  323. DCHECK(ok);
  324. accept_socket_ = NULL;
  325. base::ResetAndReturn(&accept_callback_).Run(rv);
  326. }
  327. int SocketPosix::DoConnect() {
  328. int rv = HANDLE_EINTR(connect(socket_fd_,
  329. peer_address_->addr,
  330. peer_address_->addr_len));
  331. DCHECK_GE(0, rv);
  332. return rv == 0 ? OK : MapConnectError(errno);
  333. }
  334. void SocketPosix::ConnectCompleted() {
  335. // Get the error that connect() completed with.
  336. int os_error = 0;
  337. socklen_t len = sizeof(os_error);
  338. if (getsockopt(socket_fd_, SOL_SOCKET, SO_ERROR, &os_error, &len) == 0) {
  339. // TCPSocketPosix expects errno to be set.
  340. errno = os_error;
  341. }
  342. int rv = MapConnectError(errno);
  343. if (rv == ERR_IO_PENDING)
  344. return;
  345. bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
  346. DCHECK(ok);
  347. waiting_connect_ = false;
  348. base::ResetAndReturn(&write_callback_).Run(rv);
  349. }
  350. int SocketPosix::DoRead(IOBuffer* buf, int buf_len) {
  351. int rv = HANDLE_EINTR(read(socket_fd_, buf->data(), buf_len));
  352. return rv >= 0 ? rv : MapSystemError(errno);
  353. }
  354. void SocketPosix::ReadCompleted() {
  355. int rv = DoRead(read_buf_.get(), read_buf_len_);
  356. if (rv == ERR_IO_PENDING)
  357. return;
  358. bool ok = read_socket_watcher_.StopWatchingFileDescriptor();
  359. DCHECK(ok);
  360. read_buf_ = NULL;
  361. read_buf_len_ = 0;
  362. base::ResetAndReturn(&read_callback_).Run(rv);
  363. }
  364. int SocketPosix::DoWrite(IOBuffer* buf, int buf_len) {
  365. int rv = HANDLE_EINTR(write(socket_fd_, buf->data(), buf_len));
  366. return rv >= 0 ? rv : MapSystemError(errno);
  367. }
  368. void SocketPosix::WriteCompleted() {
  369. int rv = DoWrite(write_buf_.get(), write_buf_len_);
  370. if (rv == ERR_IO_PENDING)
  371. return;
  372. bool ok = write_socket_watcher_.StopWatchingFileDescriptor();
  373. DCHECK(ok);
  374. write_buf_ = NULL;
  375. write_buf_len_ = 0;
  376. base::ResetAndReturn(&write_callback_).Run(rv);
  377. }
  378. void SocketPosix::StopWatchingAndCleanUp() {
  379. bool ok = accept_socket_watcher_.StopWatchingFileDescriptor();
  380. DCHECK(ok);
  381. ok = read_socket_watcher_.StopWatchingFileDescriptor();
  382. DCHECK(ok);
  383. ok = write_socket_watcher_.StopWatchingFileDescriptor();
  384. DCHECK(ok);
  385. if (!accept_callback_.is_null()) {
  386. accept_socket_ = NULL;
  387. accept_callback_.Reset();
  388. }
  389. if (!read_callback_.is_null()) {
  390. read_buf_ = NULL;
  391. read_buf_len_ = 0;
  392. read_callback_.Reset();
  393. }
  394. if (!write_callback_.is_null()) {
  395. write_buf_ = NULL;
  396. write_buf_len_ = 0;
  397. write_callback_.Reset();
  398. }
  399. waiting_connect_ = false;
  400. peer_address_.reset();
  401. }
  402. } // namespace net