Line data Source code
1 : #include "source/extensions/transport_sockets/tls/io_handle_bio.h" 2 : 3 : #include "envoy/buffer/buffer.h" 4 : #include "envoy/network/io_handle.h" 5 : 6 : #include "openssl/bio.h" 7 : #include "openssl/err.h" 8 : 9 : namespace Envoy { 10 : namespace Extensions { 11 : namespace TransportSockets { 12 : namespace Tls { 13 : 14 : namespace { 15 : 16 : // NOLINTNEXTLINE(readability-identifier-naming) 17 0 : inline Envoy::Network::IoHandle* bio_io_handle(BIO* bio) { 18 0 : return reinterpret_cast<Envoy::Network::IoHandle*>(bio->ptr); 19 0 : } 20 : 21 : // NOLINTNEXTLINE(readability-identifier-naming) 22 0 : int io_handle_new(BIO* bio) { 23 0 : bio->init = 0; 24 0 : bio->num = -1; 25 0 : bio->ptr = nullptr; 26 0 : bio->flags = 0; 27 0 : return 1; 28 0 : } 29 : 30 : // NOLINTNEXTLINE(readability-identifier-naming) 31 0 : int io_handle_free(BIO* bio) { 32 0 : if (bio == nullptr) { 33 0 : return 0; 34 0 : } 35 : 36 0 : if (bio->shutdown) { 37 0 : if (bio->init) { 38 0 : bio_io_handle(bio)->close(); 39 0 : } 40 0 : bio->init = 0; 41 0 : bio->flags = 0; 42 0 : } 43 0 : return 1; 44 0 : } 45 : 46 : // NOLINTNEXTLINE(readability-identifier-naming) 47 0 : int io_handle_read(BIO* b, char* out, int outl) { 48 0 : if (out == nullptr) { 49 0 : return 0; 50 0 : } 51 : 52 0 : Envoy::Buffer::RawSlice slice; 53 0 : slice.mem_ = out; 54 0 : slice.len_ = outl; 55 0 : auto result = bio_io_handle(b)->readv(outl, &slice, 1); 56 0 : BIO_clear_retry_flags(b); 57 0 : if (!result.ok()) { 58 0 : auto err = result.err_->getErrorCode(); 59 0 : if (err == Api::IoError::IoErrorCode::Again || err == Api::IoError::IoErrorCode::Interrupt) { 60 0 : BIO_set_retry_read(b); 61 0 : } else { 62 0 : ERR_put_error(ERR_LIB_SYS, 0, result.err_->getSystemErrorCode(), __FILE__, __LINE__); 63 0 : } 64 0 : return -1; 65 0 : } 66 0 : return result.return_value_; 67 0 : } 68 : 69 : // NOLINTNEXTLINE(readability-identifier-naming) 70 0 : int io_handle_write(BIO* b, const char* in, int inl) { 71 0 : Envoy::Buffer::RawSlice slice; 72 0 : slice.mem_ = const_cast<char*>(in); 73 0 : slice.len_ = inl; 74 0 : auto result = bio_io_handle(b)->writev(&slice, 1); 75 0 : BIO_clear_retry_flags(b); 76 0 : if (!result.ok()) { 77 0 : auto err = result.err_->getErrorCode(); 78 0 : if (err == Api::IoError::IoErrorCode::Again || err == Api::IoError::IoErrorCode::Interrupt) { 79 0 : BIO_set_retry_write(b); 80 0 : } else { 81 0 : ERR_put_error(ERR_LIB_SYS, 0, result.err_->getSystemErrorCode(), __FILE__, __LINE__); 82 0 : } 83 0 : return -1; 84 0 : } 85 0 : return result.return_value_; 86 0 : } 87 : 88 : // NOLINTNEXTLINE(readability-identifier-naming) 89 0 : long io_handle_ctrl(BIO* b, int cmd, long num, void*) { 90 0 : long ret = 1; 91 : 92 0 : switch (cmd) { 93 0 : case BIO_C_SET_FD: 94 0 : RELEASE_ASSERT(false, "should not be called"); 95 0 : break; 96 0 : case BIO_C_GET_FD: 97 0 : RELEASE_ASSERT(false, "should not be called"); 98 0 : break; 99 0 : case BIO_CTRL_GET_CLOSE: 100 0 : ret = b->shutdown; 101 0 : break; 102 0 : case BIO_CTRL_SET_CLOSE: 103 0 : b->shutdown = int(num); 104 0 : break; 105 0 : case BIO_CTRL_FLUSH: 106 0 : ret = 1; 107 0 : break; 108 0 : default: 109 0 : ret = 0; 110 0 : break; 111 0 : } 112 0 : return ret; 113 0 : } 114 : 115 : const BIO_METHOD methods_io_handlep = { 116 : BIO_TYPE_SOCKET, "io_handle", 117 : io_handle_write, io_handle_read, 118 : nullptr /* puts */, nullptr /* gets, */, 119 : io_handle_ctrl, io_handle_new, 120 : io_handle_free, nullptr /* callback_ctrl */, 121 : }; 122 : 123 : // NOLINTNEXTLINE(readability-identifier-naming) 124 0 : const BIO_METHOD* BIO_s_io_handle(void) { return &methods_io_handlep; } 125 : 126 : } // namespace 127 : 128 : // NOLINTNEXTLINE(readability-identifier-naming) 129 0 : BIO* BIO_new_io_handle(Envoy::Network::IoHandle* io_handle) { 130 0 : BIO* b; 131 : 132 0 : b = BIO_new(BIO_s_io_handle()); 133 0 : RELEASE_ASSERT(b != nullptr, ""); 134 : 135 : // Initialize the BIO 136 0 : b->num = -1; 137 0 : b->ptr = io_handle; 138 0 : b->shutdown = 0; 139 0 : b->init = 1; 140 : 141 0 : return b; 142 0 : } 143 : 144 : } // namespace Tls 145 : } // namespace TransportSockets 146 : } // namespace Extensions 147 : } // namespace Envoy