Line data Source code
1 : // Copyright (c) 2021-2022 The Bitcoin Core developers 2 : // Distributed under the MIT software license, see the accompanying 3 : // file COPYING or http://www.opensource.org/licenses/mit-license.php. 4 : #include <util/tokenpipe.h> 5 : 6 : #if defined(HAVE_CONFIG_H) 7 : #include <config/bitcoin-config.h> 8 : #endif 9 : 10 : #ifndef WIN32 11 : 12 : #include <errno.h> 13 : #include <fcntl.h> 14 : #include <optional> 15 : #include <unistd.h> 16 : 17 1 : TokenPipeEnd TokenPipe::TakeReadEnd() 18 : { 19 1 : TokenPipeEnd res(m_fds[0]); 20 1 : m_fds[0] = -1; 21 1 : return res; 22 1 : } 23 : 24 1 : TokenPipeEnd TokenPipe::TakeWriteEnd() 25 : { 26 1 : TokenPipeEnd res(m_fds[1]); 27 1 : m_fds[1] = -1; 28 1 : return res; 29 1 : } 30 : 31 4 : TokenPipeEnd::TokenPipeEnd(int fd) : m_fd(fd) 32 : { 33 4 : } 34 : 35 4 : TokenPipeEnd::~TokenPipeEnd() 36 : { 37 4 : Close(); 38 4 : } 39 : 40 0 : int TokenPipeEnd::TokenWrite(uint8_t token) 41 : { 42 0 : while (true) { 43 0 : ssize_t result = write(m_fd, &token, 1); 44 0 : if (result < 0) { 45 : // Failure. It's possible that the write was interrupted by a signal, 46 : // in that case retry. 47 0 : if (errno != EINTR) { 48 0 : return TS_ERR; 49 : } 50 0 : } else if (result == 0) { 51 0 : return TS_EOS; 52 : } else { // ==1 53 0 : return 0; 54 : } 55 : } 56 0 : } 57 : 58 0 : int TokenPipeEnd::TokenRead() 59 : { 60 : uint8_t token; 61 0 : while (true) { 62 0 : ssize_t result = read(m_fd, &token, 1); 63 0 : if (result < 0) { 64 : // Failure. Check if the read was interrupted by a signal, 65 : // in that case retry. 66 0 : if (errno != EINTR) { 67 0 : return TS_ERR; 68 : } 69 0 : } else if (result == 0) { 70 0 : return TS_EOS; 71 : } else { // ==1 72 0 : return token; 73 : } 74 : } 75 : return token; 76 0 : } 77 : 78 6 : void TokenPipeEnd::Close() 79 : { 80 6 : if (m_fd != -1) close(m_fd); 81 6 : m_fd = -1; 82 6 : } 83 : 84 1 : std::optional<TokenPipe> TokenPipe::Make() 85 : { 86 1 : int fds[2] = {-1, -1}; 87 : #if HAVE_O_CLOEXEC && HAVE_DECL_PIPE2 88 1 : if (pipe2(fds, O_CLOEXEC) != 0) { 89 0 : return std::nullopt; 90 : } 91 : #else 92 : if (pipe(fds) != 0) { 93 : return std::nullopt; 94 : } 95 : #endif 96 1 : return TokenPipe(fds); 97 1 : } 98 : 99 2 : TokenPipe::~TokenPipe() 100 : { 101 2 : Close(); 102 2 : } 103 : 104 2 : void TokenPipe::Close() 105 : { 106 2 : if (m_fds[0] != -1) close(m_fds[0]); 107 2 : if (m_fds[1] != -1) close(m_fds[1]); 108 2 : m_fds[0] = m_fds[1] = -1; 109 2 : } 110 : 111 : #endif // WIN32