src: replace naive search in Buffer::IndexOf
[platform/upstream/nodejs.git] / src / node_crypto_bio.h
1 #ifndef SRC_NODE_CRYPTO_BIO_H_
2 #define SRC_NODE_CRYPTO_BIO_H_
3
4 #include "openssl/bio.h"
5 #include "env.h"
6 #include "env-inl.h"
7 #include "util.h"
8 #include "util-inl.h"
9 #include "v8.h"
10
11 namespace node {
12
13 class NodeBIO {
14  public:
15   NodeBIO() : env_(nullptr),
16               initial_(kInitialBufferLength),
17               length_(0),
18               read_head_(nullptr),
19               write_head_(nullptr) {
20   }
21
22   ~NodeBIO();
23
24   static BIO* New();
25
26   void AssignEnvironment(Environment* env);
27
28   // Move read head to next buffer if needed
29   void TryMoveReadHead();
30
31   // Allocate new buffer for write if needed
32   void TryAllocateForWrite(size_t hint);
33
34   // Read `len` bytes maximum into `out`, return actual number of read bytes
35   size_t Read(char* out, size_t size);
36
37   // Memory optimization:
38   // Deallocate children of write head's child if they're empty
39   void FreeEmpty();
40
41   // Return pointer to internal data and amount of
42   // contiguous data available to read
43   char* Peek(size_t* size);
44
45   // Return pointers and sizes of multiple internal data chunks available for
46   // reading
47   size_t PeekMultiple(char** out, size_t* size, size_t* count);
48
49   // Find first appearance of `delim` in buffer or `limit` if `delim`
50   // wasn't found.
51   size_t IndexOf(char delim, size_t limit);
52
53   // Discard all available data
54   void Reset();
55
56   // Put `len` bytes from `data` into buffer
57   void Write(const char* data, size_t size);
58
59   // Return pointer to internal data and amount of
60   // contiguous data available for future writes
61   char* PeekWritable(size_t* size);
62
63   // Commit reserved data
64   void Commit(size_t size);
65
66
67   // Return size of buffer in bytes
68   inline size_t Length() const {
69     return length_;
70   }
71
72   inline void set_initial(size_t initial) {
73     initial_ = initial;
74   }
75
76   static inline NodeBIO* FromBIO(BIO* bio) {
77     CHECK_NE(bio->ptr, nullptr);
78     return static_cast<NodeBIO*>(bio->ptr);
79   }
80
81  private:
82   static int New(BIO* bio);
83   static int Free(BIO* bio);
84   static int Read(BIO* bio, char* out, int len);
85   static int Write(BIO* bio, const char* data, int len);
86   static int Puts(BIO* bio, const char* str);
87   static int Gets(BIO* bio, char* out, int size);
88   static long Ctrl(BIO* bio, int cmd, long num, void* ptr);
89
90   // Enough to handle the most of the client hellos
91   static const size_t kInitialBufferLength = 1024;
92   static const size_t kThroughputBufferLength = 16384;
93
94   static const BIO_METHOD method;
95
96   class Buffer {
97    public:
98     Buffer(Environment* env, size_t len) : env_(env),
99                                            read_pos_(0),
100                                            write_pos_(0),
101                                            len_(len),
102                                            next_(nullptr) {
103       data_ = new char[len];
104       if (env_ != nullptr)
105         env_->isolate()->AdjustAmountOfExternalAllocatedMemory(len);
106     }
107
108     ~Buffer() {
109       delete[] data_;
110       if (env_ != nullptr) {
111         const int64_t len = static_cast<int64_t>(len_);
112         env_->isolate()->AdjustAmountOfExternalAllocatedMemory(-len);
113       }
114     }
115
116     Environment* env_;
117     size_t read_pos_;
118     size_t write_pos_;
119     size_t len_;
120     Buffer* next_;
121     char* data_;
122   };
123
124   Environment* env_;
125   size_t initial_;
126   size_t length_;
127   Buffer* read_head_;
128   Buffer* write_head_;
129 };
130
131 }  // namespace node
132
133 #endif  // SRC_NODE_CRYPTO_BIO_H_