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 0 : TokenPipeEnd TokenPipe::TakeReadEnd() 17 : { 18 0 : TokenPipeEnd res(m_fds[0]); 19 0 : m_fds[0] = -1; 20 0 : return res; 21 0 : } 22 : 23 0 : TokenPipeEnd TokenPipe::TakeWriteEnd() 24 : { 25 0 : TokenPipeEnd res(m_fds[1]); 26 0 : m_fds[1] = -1; 27 0 : return res; 28 0 : } 29 : 30 584 : TokenPipeEnd::TokenPipeEnd(int fd) : m_fd(fd) 31 292 : { 32 584 : } 33 : 34 0 : TokenPipeEnd::~TokenPipeEnd() 35 0 : { 36 0 : Close(); 37 0 : } 38 : 39 0 : int TokenPipeEnd::TokenWrite(uint8_t token) 40 : { 41 0 : while (true) { 42 0 : ssize_t result = write(m_fd, &token, 1); 43 0 : 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 0 : } else if (result == 0) { 50 0 : return TS_EOS; 51 : } else { // ==1 52 0 : return 0; 53 : } 54 : } 55 0 : } 56 : 57 0 : int TokenPipeEnd::TokenRead() 58 : { 59 : uint8_t token; 60 0 : while (true) { 61 0 : ssize_t result = read(m_fd, &token, 1); 62 0 : if (result < 0) { 63 : // Failure. Check if the read was interrupted by a signal, 64 : // in that case retry. 65 0 : if (errno != EINTR) { 66 0 : return TS_ERR; 67 : } 68 0 : } else if (result == 0) { 69 0 : return TS_EOS; 70 : } else { // ==1 71 0 : return token; 72 : } 73 : } 74 : return token; 75 0 : } 76 : 77 0 : void TokenPipeEnd::Close() 78 : { 79 0 : if (m_fd != -1) close(m_fd); 80 0 : m_fd = -1; 81 0 : } 82 : 83 0 : std::optional<TokenPipe> TokenPipe::Make() 84 : { 85 0 : 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 0 : if (pipe(fds) != 0) { 92 0 : return std::nullopt; 93 : } 94 : #endif 95 0 : return TokenPipe(fds); 96 0 : } 97 : 98 0 : TokenPipe::~TokenPipe() 99 0 : { 100 0 : Close(); 101 0 : } 102 : 103 0 : void TokenPipe::Close() 104 : { 105 0 : if (m_fds[0] != -1) close(m_fds[0]); 106 0 : if (m_fds[1] != -1) close(m_fds[1]); 107 0 : m_fds[0] = m_fds[1] = -1; 108 0 : } 109 : 110 : #endif // WIN32