Stream.cpp 16 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631
  1. /*
  2. * Copyright (c) 2018-2021, Andreas Kling <kling@serenityos.org>
  3. * Copyright (c) 2021, sin-ack <sin-ack@protonmail.com>
  4. *
  5. * SPDX-License-Identifier: BSD-2-Clause
  6. */
  7. #include "Stream.h"
  8. #include <LibCore/System.h>
  9. #include <fcntl.h>
  10. #include <netdb.h>
  11. #include <poll.h>
  12. #include <sys/ioctl.h>
  13. #include <sys/socket.h>
  14. #include <sys/types.h>
  15. #include <unistd.h>
  16. #ifdef __serenity__
  17. # include <serenity.h>
  18. #endif
  19. #ifdef __FreeBSD__
  20. # include <sys/ucred.h>
  21. #endif
  22. namespace Core::Stream {
  23. bool Stream::read_or_error(Bytes buffer)
  24. {
  25. VERIFY(buffer.size());
  26. size_t nread = 0;
  27. do {
  28. if (is_eof())
  29. return false;
  30. auto result = read(buffer.slice(nread));
  31. if (result.is_error()) {
  32. if (result.error().is_errno() && result.error().code() == EINTR) {
  33. continue;
  34. }
  35. return false;
  36. }
  37. nread += result.value().size();
  38. } while (nread < buffer.size());
  39. return true;
  40. }
  41. ErrorOr<ByteBuffer> Stream::read_all(size_t block_size)
  42. {
  43. return read_all_impl(block_size);
  44. }
  45. ErrorOr<ByteBuffer> Stream::read_all_impl(size_t block_size, size_t expected_file_size)
  46. {
  47. ByteBuffer data;
  48. data.ensure_capacity(file_size);
  49. size_t total_read {};
  50. size_t next_reading_size { block_size };
  51. for (Span<u8> chunk; !is_eof();) {
  52. if (next_reading_size == block_size)
  53. chunk = TRY(data.get_bytes_for_writing(next_reading_size));
  54. auto const nread = TRY(read(chunk)).size();
  55. next_reading_size -= nread;
  56. if (next_reading_size == 0)
  57. next_reading_size = block_size;
  58. total_read += nread;
  59. if (nread < block_size)
  60. data.resize(total_read);
  61. }
  62. return data;
  63. }
  64. bool Stream::write_or_error(ReadonlyBytes buffer)
  65. {
  66. VERIFY(buffer.size());
  67. size_t nwritten = 0;
  68. do {
  69. auto result = write(buffer.slice(nwritten));
  70. if (result.is_error()) {
  71. if (result.error().is_errno() && result.error().code() == EINTR) {
  72. continue;
  73. }
  74. return false;
  75. }
  76. nwritten += result.value();
  77. } while (nwritten < buffer.size());
  78. return true;
  79. }
  80. ErrorOr<off_t> SeekableStream::tell() const
  81. {
  82. // Seek with 0 and SEEK_CUR does not modify anything despite the const_cast,
  83. // so it's safe to do this.
  84. return const_cast<SeekableStream*>(this)->seek(0, SeekMode::FromCurrentPosition);
  85. }
  86. ErrorOr<off_t> SeekableStream::size()
  87. {
  88. auto original_position = TRY(tell());
  89. auto seek_result = seek(0, SeekMode::FromEndPosition);
  90. if (seek_result.is_error()) {
  91. // Let's try to restore the original position, just in case.
  92. auto restore_result = seek(original_position, SeekMode::SetPosition);
  93. if (restore_result.is_error()) {
  94. dbgln("Core::SeekableStream::size: Couldn't restore initial position, stream might have incorrect position now!");
  95. }
  96. return seek_result.release_error();
  97. }
  98. TRY(seek(original_position, SeekMode::SetPosition));
  99. return seek_result.value();
  100. }
  101. ErrorOr<NonnullOwnPtr<File>> File::open(StringView filename, OpenMode mode, mode_t permissions)
  102. {
  103. auto file = TRY(adopt_nonnull_own_or_enomem(new (nothrow) File(mode)));
  104. TRY(file->open_path(filename, permissions));
  105. return file;
  106. }
  107. ErrorOr<NonnullOwnPtr<File>> File::adopt_fd(int fd, OpenMode mode)
  108. {
  109. if (fd < 0) {
  110. return Error::from_errno(EBADF);
  111. }
  112. if (!has_any_flag(mode, OpenMode::ReadWrite)) {
  113. dbgln("Core::File::adopt_fd: Attempting to adopt a file with neither Read nor Write specified in mode");
  114. return Error::from_errno(EINVAL);
  115. }
  116. auto file = TRY(adopt_nonnull_own_or_enomem(new (nothrow) File(mode)));
  117. file->m_fd = fd;
  118. return file;
  119. }
  120. bool File::exists(StringView filename)
  121. {
  122. return !Core::System::stat(filename).is_error();
  123. }
  124. ErrorOr<NonnullOwnPtr<File>> File::open_file_or_standard_stream(StringView filename, OpenMode mode)
  125. {
  126. if (!filename.is_empty() && filename != "-"sv)
  127. return File::open(filename, mode);
  128. switch (mode) {
  129. case OpenMode::Read:
  130. return File::adopt_fd(STDIN_FILENO, mode);
  131. case OpenMode::Write:
  132. return File::adopt_fd(STDOUT_FILENO, mode);
  133. default:
  134. VERIFY_NOT_REACHED();
  135. }
  136. }
  137. int File::open_mode_to_options(OpenMode mode)
  138. {
  139. int flags = 0;
  140. if (has_flag(mode, OpenMode::ReadWrite)) {
  141. flags |= O_RDWR | O_CREAT;
  142. } else if (has_flag(mode, OpenMode::Read)) {
  143. flags |= O_RDONLY;
  144. } else if (has_flag(mode, OpenMode::Write)) {
  145. flags |= O_WRONLY | O_CREAT;
  146. bool should_truncate = !has_any_flag(mode, OpenMode::Append | OpenMode::MustBeNew);
  147. if (should_truncate)
  148. flags |= O_TRUNC;
  149. }
  150. if (has_flag(mode, OpenMode::Append))
  151. flags |= O_APPEND;
  152. if (has_flag(mode, OpenMode::Truncate))
  153. flags |= O_TRUNC;
  154. if (has_flag(mode, OpenMode::MustBeNew))
  155. flags |= O_EXCL;
  156. if (!has_flag(mode, OpenMode::KeepOnExec))
  157. flags |= O_CLOEXEC;
  158. if (!has_flag(mode, OpenMode::Nonblocking))
  159. flags |= O_NONBLOCK;
  160. return flags;
  161. }
  162. ErrorOr<void> File::open_path(StringView filename, mode_t permissions)
  163. {
  164. VERIFY(m_fd == -1);
  165. auto flags = open_mode_to_options(m_mode);
  166. m_fd = TRY(System::open(filename, flags, permissions));
  167. return {};
  168. }
  169. bool File::is_readable() const { return has_flag(m_mode, OpenMode::Read); }
  170. bool File::is_writable() const { return has_flag(m_mode, OpenMode::Write); }
  171. ErrorOr<Bytes> File::read(Bytes buffer)
  172. {
  173. if (!has_flag(m_mode, OpenMode::Read)) {
  174. // NOTE: POSIX says that if the fd is not open for reading, the call
  175. // will return EBADF. Since we already know whether we can or
  176. // can't read the file, let's avoid a syscall.
  177. return Error::from_errno(EBADF);
  178. }
  179. ssize_t nread = TRY(System::read(m_fd, buffer));
  180. m_last_read_was_eof = nread == 0;
  181. return buffer.trim(nread);
  182. }
  183. ErrorOr<ByteBuffer> File::read_all(size_t block_size)
  184. {
  185. // Note: This is used as a heuristic, it's not valid for devices or virtual files.
  186. auto const potential_file_size = TRY(System::fstat(m_fd)).st_size;
  187. return read_all_impl(block_size, potential_file_size);
  188. }
  189. ErrorOr<size_t> File::write(ReadonlyBytes buffer)
  190. {
  191. if (!has_flag(m_mode, OpenMode::Write)) {
  192. // NOTE: Same deal as Read.
  193. return Error::from_errno(EBADF);
  194. }
  195. return TRY(System::write(m_fd, buffer));
  196. }
  197. bool File::is_eof() const { return m_last_read_was_eof; }
  198. bool File::is_open() const { return m_fd >= 0; }
  199. void File::close()
  200. {
  201. if (!is_open()) {
  202. return;
  203. }
  204. // NOTE: The closing of the file can be interrupted by a signal, in which
  205. // case EINTR will be returned by the close syscall. So let's try closing
  206. // the file until we aren't interrupted by rude signals. :^)
  207. ErrorOr<void> result;
  208. do {
  209. result = System::close(m_fd);
  210. } while (result.is_error() && result.error().code() == EINTR);
  211. VERIFY(!result.is_error());
  212. m_fd = -1;
  213. }
  214. ErrorOr<off_t> File::seek(i64 offset, SeekMode mode)
  215. {
  216. int syscall_mode;
  217. switch (mode) {
  218. case SeekMode::SetPosition:
  219. syscall_mode = SEEK_SET;
  220. break;
  221. case SeekMode::FromCurrentPosition:
  222. syscall_mode = SEEK_CUR;
  223. break;
  224. case SeekMode::FromEndPosition:
  225. syscall_mode = SEEK_END;
  226. break;
  227. default:
  228. VERIFY_NOT_REACHED();
  229. }
  230. off_t seek_result = TRY(System::lseek(m_fd, offset, syscall_mode));
  231. m_last_read_was_eof = false;
  232. return seek_result;
  233. }
  234. ErrorOr<void> File::truncate(off_t length)
  235. {
  236. return System::ftruncate(m_fd, length);
  237. }
  238. ErrorOr<int> Socket::create_fd(SocketDomain domain, SocketType type)
  239. {
  240. int socket_domain;
  241. switch (domain) {
  242. case SocketDomain::Inet:
  243. socket_domain = AF_INET;
  244. break;
  245. case SocketDomain::Local:
  246. socket_domain = AF_LOCAL;
  247. break;
  248. default:
  249. VERIFY_NOT_REACHED();
  250. }
  251. int socket_type;
  252. switch (type) {
  253. case SocketType::Stream:
  254. socket_type = SOCK_STREAM;
  255. break;
  256. case SocketType::Datagram:
  257. socket_type = SOCK_DGRAM;
  258. break;
  259. default:
  260. VERIFY_NOT_REACHED();
  261. }
  262. // Let's have a safe default of CLOEXEC. :^)
  263. #ifdef SOCK_CLOEXEC
  264. return System::socket(socket_domain, socket_type | SOCK_CLOEXEC, 0);
  265. #else
  266. auto fd = TRY(System::socket(socket_domain, socket_type, 0));
  267. TRY(System::fcntl(fd, F_SETFD, FD_CLOEXEC));
  268. return fd;
  269. #endif
  270. }
  271. ErrorOr<IPv4Address> Socket::resolve_host(String const& host, SocketType type)
  272. {
  273. int socket_type;
  274. switch (type) {
  275. case SocketType::Stream:
  276. socket_type = SOCK_STREAM;
  277. break;
  278. case SocketType::Datagram:
  279. socket_type = SOCK_DGRAM;
  280. break;
  281. default:
  282. VERIFY_NOT_REACHED();
  283. }
  284. struct addrinfo hints = {};
  285. hints.ai_family = AF_UNSPEC;
  286. hints.ai_socktype = socket_type;
  287. hints.ai_flags = 0;
  288. hints.ai_protocol = 0;
  289. // FIXME: Convert this to Core::System
  290. struct addrinfo* results = nullptr;
  291. int rc = getaddrinfo(host.characters(), nullptr, &hints, &results);
  292. if (rc != 0) {
  293. if (rc == EAI_SYSTEM) {
  294. return Error::from_syscall("getaddrinfo"sv, -errno);
  295. }
  296. auto const* error_string = gai_strerror(rc);
  297. return Error::from_string_view({ error_string, strlen(error_string) });
  298. }
  299. auto* socket_address = bit_cast<struct sockaddr_in*>(results->ai_addr);
  300. NetworkOrdered<u32> network_ordered_address { socket_address->sin_addr.s_addr };
  301. freeaddrinfo(results);
  302. return IPv4Address { network_ordered_address };
  303. }
  304. ErrorOr<void> Socket::connect_local(int fd, String const& path)
  305. {
  306. auto address = SocketAddress::local(path);
  307. auto maybe_sockaddr = address.to_sockaddr_un();
  308. if (!maybe_sockaddr.has_value()) {
  309. dbgln("Core::Stream::Socket::connect_local: Could not obtain a sockaddr_un");
  310. return Error::from_errno(EINVAL);
  311. }
  312. auto addr = maybe_sockaddr.release_value();
  313. return System::connect(fd, bit_cast<struct sockaddr*>(&addr), sizeof(addr));
  314. }
  315. ErrorOr<void> Socket::connect_inet(int fd, SocketAddress const& address)
  316. {
  317. auto addr = address.to_sockaddr_in();
  318. return System::connect(fd, bit_cast<struct sockaddr*>(&addr), sizeof(addr));
  319. }
  320. ErrorOr<Bytes> PosixSocketHelper::read(Bytes buffer, int flags)
  321. {
  322. if (!is_open()) {
  323. return Error::from_errno(ENOTCONN);
  324. }
  325. ssize_t nread = TRY(System::recv(m_fd, buffer.data(), buffer.size(), flags));
  326. m_last_read_was_eof = nread == 0;
  327. // If a socket read is EOF, then no more data can be read from it because
  328. // the protocol has disconnected. In this case, we can just disable the
  329. // notifier if we have one.
  330. if (m_last_read_was_eof && m_notifier)
  331. m_notifier->set_enabled(false);
  332. return buffer.trim(nread);
  333. }
  334. ErrorOr<size_t> PosixSocketHelper::write(ReadonlyBytes buffer)
  335. {
  336. if (!is_open()) {
  337. return Error::from_errno(ENOTCONN);
  338. }
  339. return TRY(System::send(m_fd, buffer.data(), buffer.size(), 0));
  340. }
  341. void PosixSocketHelper::close()
  342. {
  343. if (!is_open()) {
  344. return;
  345. }
  346. if (m_notifier)
  347. m_notifier->set_enabled(false);
  348. ErrorOr<void> result;
  349. do {
  350. result = System::close(m_fd);
  351. } while (result.is_error() && result.error().code() == EINTR);
  352. VERIFY(!result.is_error());
  353. m_fd = -1;
  354. }
  355. ErrorOr<bool> PosixSocketHelper::can_read_without_blocking(int timeout) const
  356. {
  357. struct pollfd the_fd = { .fd = m_fd, .events = POLLIN, .revents = 0 };
  358. // FIXME: Convert this to Core::System
  359. int rc;
  360. do {
  361. rc = ::poll(&the_fd, 1, timeout);
  362. } while (rc < 0 && errno == EINTR);
  363. if (rc < 0) {
  364. return Error::from_syscall("poll"sv, -errno);
  365. }
  366. return (the_fd.revents & POLLIN) > 0;
  367. }
  368. ErrorOr<void> PosixSocketHelper::set_blocking(bool enabled)
  369. {
  370. int value = enabled ? 0 : 1;
  371. return System::ioctl(m_fd, FIONBIO, &value);
  372. }
  373. ErrorOr<void> PosixSocketHelper::set_close_on_exec(bool enabled)
  374. {
  375. int flags = TRY(System::fcntl(m_fd, F_GETFD));
  376. if (enabled)
  377. flags |= FD_CLOEXEC;
  378. else
  379. flags &= ~FD_CLOEXEC;
  380. TRY(System::fcntl(m_fd, F_SETFD, flags));
  381. return {};
  382. }
  383. ErrorOr<void> PosixSocketHelper::set_receive_timeout(Time timeout)
  384. {
  385. auto timeout_spec = timeout.to_timespec();
  386. return System::setsockopt(m_fd, SOL_SOCKET, SO_RCVTIMEO, &timeout_spec, sizeof(timeout_spec));
  387. }
  388. void PosixSocketHelper::setup_notifier()
  389. {
  390. if (!m_notifier)
  391. m_notifier = Core::Notifier::construct(m_fd, Core::Notifier::Read);
  392. }
  393. ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::connect(String const& host, u16 port)
  394. {
  395. auto ip_address = TRY(resolve_host(host, SocketType::Stream));
  396. return connect(SocketAddress { ip_address, port });
  397. }
  398. ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::connect(SocketAddress const& address)
  399. {
  400. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) TCPSocket()));
  401. auto fd = TRY(create_fd(SocketDomain::Inet, SocketType::Stream));
  402. socket->m_helper.set_fd(fd);
  403. TRY(connect_inet(fd, address));
  404. socket->setup_notifier();
  405. return socket;
  406. }
  407. ErrorOr<NonnullOwnPtr<TCPSocket>> TCPSocket::adopt_fd(int fd)
  408. {
  409. if (fd < 0) {
  410. return Error::from_errno(EBADF);
  411. }
  412. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) TCPSocket()));
  413. socket->m_helper.set_fd(fd);
  414. socket->setup_notifier();
  415. return socket;
  416. }
  417. ErrorOr<size_t> PosixSocketHelper::pending_bytes() const
  418. {
  419. if (!is_open()) {
  420. return Error::from_errno(ENOTCONN);
  421. }
  422. int value;
  423. TRY(System::ioctl(m_fd, FIONREAD, &value));
  424. return static_cast<size_t>(value);
  425. }
  426. ErrorOr<NonnullOwnPtr<UDPSocket>> UDPSocket::connect(String const& host, u16 port, Optional<Time> timeout)
  427. {
  428. auto ip_address = TRY(resolve_host(host, SocketType::Datagram));
  429. return connect(SocketAddress { ip_address, port }, timeout);
  430. }
  431. ErrorOr<NonnullOwnPtr<UDPSocket>> UDPSocket::connect(SocketAddress const& address, Optional<Time> timeout)
  432. {
  433. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) UDPSocket()));
  434. auto fd = TRY(create_fd(SocketDomain::Inet, SocketType::Datagram));
  435. socket->m_helper.set_fd(fd);
  436. if (timeout.has_value()) {
  437. TRY(socket->m_helper.set_receive_timeout(timeout.value()));
  438. }
  439. TRY(connect_inet(fd, address));
  440. socket->setup_notifier();
  441. return socket;
  442. }
  443. ErrorOr<NonnullOwnPtr<LocalSocket>> LocalSocket::connect(String const& path)
  444. {
  445. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) LocalSocket()));
  446. auto fd = TRY(create_fd(SocketDomain::Local, SocketType::Stream));
  447. socket->m_helper.set_fd(fd);
  448. TRY(connect_local(fd, path));
  449. socket->setup_notifier();
  450. return socket;
  451. }
  452. ErrorOr<NonnullOwnPtr<LocalSocket>> LocalSocket::adopt_fd(int fd)
  453. {
  454. if (fd < 0) {
  455. return Error::from_errno(EBADF);
  456. }
  457. auto socket = TRY(adopt_nonnull_own_or_enomem(new (nothrow) LocalSocket()));
  458. socket->m_helper.set_fd(fd);
  459. socket->setup_notifier();
  460. return socket;
  461. }
  462. ErrorOr<int> LocalSocket::receive_fd(int flags)
  463. {
  464. #ifdef __serenity__
  465. return Core::System::recvfd(m_helper.fd(), flags);
  466. #else
  467. (void)flags;
  468. return Error::from_string_literal("File descriptor passing not supported on this platform");
  469. #endif
  470. }
  471. ErrorOr<void> LocalSocket::send_fd(int fd)
  472. {
  473. #ifdef __serenity__
  474. return Core::System::sendfd(m_helper.fd(), fd);
  475. #else
  476. (void)fd;
  477. return Error::from_string_literal("File descriptor passing not supported on this platform");
  478. #endif
  479. }
  480. ErrorOr<pid_t> LocalSocket::peer_pid() const
  481. {
  482. #ifdef AK_OS_MACOS
  483. pid_t pid;
  484. socklen_t pid_size = sizeof(pid);
  485. #elif defined(__FreeBSD__)
  486. struct xucred creds = {};
  487. socklen_t creds_size = sizeof(creds);
  488. #elif defined(__OpenBSD__)
  489. struct sockpeercred creds = {};
  490. socklen_t creds_size = sizeof(creds);
  491. #else
  492. struct ucred creds = {};
  493. socklen_t creds_size = sizeof(creds);
  494. #endif
  495. #ifdef AK_OS_MACOS
  496. TRY(System::getsockopt(m_helper.fd(), SOL_LOCAL, LOCAL_PEERPID, &pid, &pid_size));
  497. return pid;
  498. #elif defined(__FreeBSD__)
  499. TRY(System::getsockopt(m_helper.fd(), SOL_LOCAL, LOCAL_PEERCRED, &creds, &creds_size));
  500. return creds.cr_pid;
  501. #else
  502. TRY(System::getsockopt(m_helper.fd(), SOL_SOCKET, SO_PEERCRED, &creds, &creds_size));
  503. return creds.pid;
  504. #endif
  505. }
  506. ErrorOr<Bytes> LocalSocket::read_without_waiting(Bytes buffer)
  507. {
  508. return m_helper.read(buffer, MSG_DONTWAIT);
  509. }
  510. ErrorOr<int> LocalSocket::release_fd()
  511. {
  512. if (!is_open()) {
  513. return Error::from_errno(ENOTCONN);
  514. }
  515. auto fd = m_helper.fd();
  516. m_helper.set_fd(-1);
  517. return fd;
  518. }
  519. }