Line data Source code
1 : // Copyright (c) 2021 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 <unistd.h> 15 : 16 3108 : TokenPipeEnd TokenPipe::TakeReadEnd() 17 : { 18 3108 : TokenPipeEnd res(m_fds[0]); 19 3108 : m_fds[0] = -1; 20 3108 : return res; 21 3108 : } 22 : 23 3108 : TokenPipeEnd TokenPipe::TakeWriteEnd() 24 : { 25 3108 : TokenPipeEnd res(m_fds[1]); 26 3108 : m_fds[1] = -1; 27 3108 : return res; 28 3108 : } 29 : 30 31960 : TokenPipeEnd::TokenPipeEnd(int fd) : m_fd(fd) 31 15980 : { 32 31960 : } 33 : 34 18728 : TokenPipeEnd::~TokenPipeEnd() 35 9364 : { 36 9364 : Close(); 37 18728 : } 38 : 39 2847 : int TokenPipeEnd::TokenWrite(uint8_t token) 40 : { 41 2847 : while (true) { 42 2847 : ssize_t result = write(m_fd, &token, 1); 43 2847 : if (result < 0) { 44 : // Failure. It's possible that the write was interrupted by a signal, 45 : // in that case retry. 46 0 : if (errno != EINTR) { 47 0 : return TS_ERR; 48 : } 49 2847 : } else if (result == 0) { 50 0 : return TS_EOS; 51 : } else { // ==1 52 2847 : return 0; 53 : } 54 : } 55 2847 : } 56 : 57 2821 : int TokenPipeEnd::TokenRead() 58 : { 59 : uint8_t token; 60 2830 : while (true) { 61 2830 : ssize_t result = read(m_fd, &token, 1); 62 2830 : if (result < 0) { 63 : // Failure. Check if the read was interrupted by a signal, 64 : // in that case retry. 65 9 : if (errno != EINTR) { 66 0 : return TS_ERR; 67 : } 68 2830 : } else if (result == 0) { 69 0 : return TS_EOS; 70 : } else { // ==1 71 2821 : return token; 72 : } 73 : } 74 : return token; 75 2821 : } 76 : 77 15580 : void TokenPipeEnd::Close() 78 : { 79 15580 : if (m_fd != -1) close(m_fd); 80 15580 : m_fd = -1; 81 15580 : } 82 : 83 3108 : std::optional<TokenPipe> TokenPipe::Make() 84 : { 85 3108 : int fds[2] = {-1, -1}; 86 : #if HAVE_O_CLOEXEC && HAVE_DECL_PIPE2 87 : if (pipe2(fds, O_CLOEXEC) != 0) { 88 : return std::nullopt; 89 : } 90 : #else 91 3108 : if (pipe(fds) != 0) { 92 0 : return std::nullopt; 93 : } 94 : #endif 95 3108 : return TokenPipe(fds); 96 3108 : } 97 : 98 12432 : TokenPipe::~TokenPipe() 99 6216 : { 100 6216 : Close(); 101 12432 : } 102 : 103 6216 : void TokenPipe::Close() 104 : { 105 6216 : if (m_fds[0] != -1) close(m_fds[0]); 106 6216 : if (m_fds[1] != -1) close(m_fds[1]); 107 6216 : m_fds[0] = m_fds[1] = -1; 108 6216 : } 109 : 110 : #endif // WIN32