1 // Copyright Joyent, Inc. and other Node contributors. 2 // 3 // Permission is hereby granted, free of charge, to any person obtaining a 4 // copy of this software and associated documentation files (the 5 // "Software"), to deal in the Software without restriction, including 6 // without limitation the rights to use, copy, modify, merge, publish, 7 // distribute, sublicense, and/or sell copies of the Software, and to permit 8 // persons to whom the Software is furnished to do so, subject to the 9 // following conditions: 10 // 11 // The above copyright notice and this permission notice shall be included 12 // in all copies or substantial portions of the Software. 13 // 14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 15 // OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 16 // MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN 17 // NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, 18 // DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR 19 // OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE 20 // USE OR OTHER DEALINGS IN THE SOFTWARE. 21 22 #ifndef SRC_NODE_CRYPTO_BIO_H_ 23 #define SRC_NODE_CRYPTO_BIO_H_ 24 25 #if defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 26 27 #include "node_crypto.h" 28 #include "openssl/bio.h" 29 #include "util.h" 30 #include "v8.h" 31 32 namespace node { 33 34 class Environment; 35 36 namespace crypto { 37 38 // This class represents buffers for OpenSSL I/O, implemented as a singly-linked 39 // list of chunks. It can be used either for writing data from Node to OpenSSL, 40 // or for reading data back, but not both. 41 // The structure is only accessed, and owned by, the OpenSSL BIOPointer 42 // (a.k.a. std::unique_ptr<BIO>). 43 class NodeBIO : public MemoryRetainer { 44 public: 45 ~NodeBIO() override; 46 47 static BIOPointer New(Environment* env = nullptr); 48 49 // NewFixed takes a copy of `len` bytes from `data` and returns a BIO that, 50 // when read from, returns those bytes followed by EOF. 51 static BIOPointer NewFixed(const char* data, size_t len, 52 Environment* env = nullptr); 53 54 // Move read head to next buffer if needed 55 void TryMoveReadHead(); 56 57 // Allocate new buffer for write if needed 58 void TryAllocateForWrite(size_t hint); 59 60 // Read `len` bytes maximum into `out`, return actual number of read bytes 61 size_t Read(char* out, size_t size); 62 63 // Memory optimization: 64 // Deallocate children of write head's child if they're empty 65 void FreeEmpty(); 66 67 // Return pointer to internal data and amount of 68 // contiguous data available to read 69 char* Peek(size_t* size); 70 71 // Return pointers and sizes of multiple internal data chunks available for 72 // reading 73 size_t PeekMultiple(char** out, size_t* size, size_t* count); 74 75 // Find first appearance of `delim` in buffer or `limit` if `delim` 76 // wasn't found. 77 size_t IndexOf(char delim, size_t limit); 78 79 // Discard all available data 80 void Reset(); 81 82 // Put `len` bytes from `data` into buffer 83 void Write(const char* data, size_t size); 84 85 // Return pointer to contiguous block of reserved data and the size available 86 // for future writes. Call Commit() once the write is complete. 87 char* PeekWritable(size_t* size); 88 89 // Specify how much data was written into the block returned by 90 // PeekWritable(). 91 void Commit(size_t size); 92 93 94 // Return size of buffer in bytes Length()95 inline size_t Length() const { 96 return length_; 97 } 98 99 // Provide a hint about the size of the next pending set of writes. TLS 100 // writes records of a maximum length of 16k of data plus a 5-byte header, 101 // a MAC (up to 20 bytes for SSLv3, TLS 1.0, TLS 1.1, and up to 32 bytes 102 // for TLS 1.2), and padding if a block cipher is used. If there is a 103 // large write this will result in potentially many buffers being 104 // allocated and gc'ed which can cause long pauses. By providing a 105 // guess about the amount of buffer space that will be needed in the 106 // next allocation this overhead is removed. set_allocate_tls_hint(size_t size)107 inline void set_allocate_tls_hint(size_t size) { 108 constexpr size_t kThreshold = 16 * 1024; 109 if (size >= kThreshold) { 110 allocate_hint_ = (size / kThreshold + 1) * (kThreshold + 5 + 32); 111 } 112 } 113 set_eof_return(int num)114 inline void set_eof_return(int num) { 115 eof_return_ = num; 116 } 117 eof_return()118 inline int eof_return() { 119 return eof_return_; 120 } 121 set_initial(size_t initial)122 inline void set_initial(size_t initial) { 123 initial_ = initial; 124 } 125 126 static NodeBIO* FromBIO(BIO* bio); 127 MemoryInfo(MemoryTracker * tracker)128 void MemoryInfo(MemoryTracker* tracker) const override { 129 tracker->TrackFieldWithSize("buffer", length_, "NodeBIO::Buffer"); 130 } 131 132 SET_MEMORY_INFO_NAME(NodeBIO) 133 SET_SELF_SIZE(NodeBIO) 134 135 private: 136 static int New(BIO* bio); 137 static int Free(BIO* bio); 138 static int Read(BIO* bio, char* out, int len); 139 static int Write(BIO* bio, const char* data, int len); 140 static int Puts(BIO* bio, const char* str); 141 static int Gets(BIO* bio, char* out, int size); 142 static long Ctrl(BIO* bio, int cmd, long num, // NOLINT(runtime/int) 143 void* ptr); 144 145 static const BIO_METHOD* GetMethod(); 146 147 // Enough to handle the most of the client hellos 148 static const size_t kInitialBufferLength = 1024; 149 static const size_t kThroughputBufferLength = 16384; 150 151 class Buffer { 152 public: Buffer(Environment * env,size_t len)153 Buffer(Environment* env, size_t len) : env_(env), 154 read_pos_(0), 155 write_pos_(0), 156 len_(len), 157 next_(nullptr) { 158 data_ = new char[len]; 159 if (env_ != nullptr) 160 env_->isolate()->AdjustAmountOfExternalAllocatedMemory(len); 161 } 162 ~Buffer()163 ~Buffer() { 164 delete[] data_; 165 if (env_ != nullptr) { 166 const int64_t len = static_cast<int64_t>(len_); 167 env_->isolate()->AdjustAmountOfExternalAllocatedMemory(-len); 168 } 169 } 170 171 Environment* env_; 172 size_t read_pos_; 173 size_t write_pos_; 174 size_t len_; 175 Buffer* next_; 176 char* data_; 177 }; 178 179 Environment* env_ = nullptr; 180 size_t initial_ = kInitialBufferLength; 181 size_t length_ = 0; 182 size_t allocate_hint_ = 0; 183 int eof_return_ = -1; 184 Buffer* read_head_ = nullptr; 185 Buffer* write_head_ = nullptr; 186 187 friend void node::crypto::InitCryptoOnce(); 188 }; 189 190 } // namespace crypto 191 } // namespace node 192 193 #endif // defined(NODE_WANT_INTERNALS) && NODE_WANT_INTERNALS 194 195 #endif // SRC_NODE_CRYPTO_BIO_H_ 196