Botan
1.11.15
|
00001 /* 00002 * SecureQueue 00003 * (C) 1999-2007 Jack Lloyd 00004 * 2012 Markus Wanner 00005 * 00006 * Botan is released under the Simplified BSD License (see license.txt) 00007 */ 00008 00009 #include <botan/secqueue.h> 00010 #include <algorithm> 00011 00012 namespace Botan { 00013 00014 /** 00015 * A node in a SecureQueue 00016 */ 00017 class SecureQueueNode 00018 { 00019 public: 00020 SecureQueueNode() : buffer(DEFAULT_BUFFERSIZE) 00021 { next = nullptr; start = end = 0; } 00022 00023 ~SecureQueueNode() { next = nullptr; start = end = 0; } 00024 00025 size_t write(const byte input[], size_t length) 00026 { 00027 size_t copied = std::min<size_t>(length, buffer.size() - end); 00028 copy_mem(&buffer[end], input, copied); 00029 end += copied; 00030 return copied; 00031 } 00032 00033 size_t read(byte output[], size_t length) 00034 { 00035 size_t copied = std::min(length, end - start); 00036 copy_mem(output, &buffer[start], copied); 00037 start += copied; 00038 return copied; 00039 } 00040 00041 size_t peek(byte output[], size_t length, size_t offset = 0) 00042 { 00043 const size_t left = end - start; 00044 if(offset >= left) return 0; 00045 size_t copied = std::min(length, left - offset); 00046 copy_mem(output, &buffer[start + offset], copied); 00047 return copied; 00048 } 00049 00050 size_t size() const { return (end - start); } 00051 private: 00052 friend class SecureQueue; 00053 SecureQueueNode* next; 00054 secure_vector<byte> buffer; 00055 size_t start, end; 00056 }; 00057 00058 /* 00059 * Create a SecureQueue 00060 */ 00061 SecureQueue::SecureQueue() 00062 { 00063 bytes_read = 0; 00064 set_next(nullptr, 0); 00065 head = tail = new SecureQueueNode; 00066 } 00067 00068 /* 00069 * Copy a SecureQueue 00070 */ 00071 SecureQueue::SecureQueue(const SecureQueue& input) : 00072 Fanout_Filter(), DataSource() 00073 { 00074 bytes_read = 0; 00075 set_next(nullptr, 0); 00076 00077 head = tail = new SecureQueueNode; 00078 SecureQueueNode* temp = input.head; 00079 while(temp) 00080 { 00081 write(&temp->buffer[temp->start], temp->end - temp->start); 00082 temp = temp->next; 00083 } 00084 } 00085 00086 /* 00087 * Destroy this SecureQueue 00088 */ 00089 void SecureQueue::destroy() 00090 { 00091 SecureQueueNode* temp = head; 00092 while(temp) 00093 { 00094 SecureQueueNode* holder = temp->next; 00095 delete temp; 00096 temp = holder; 00097 } 00098 head = tail = nullptr; 00099 } 00100 00101 /* 00102 * Copy a SecureQueue 00103 */ 00104 SecureQueue& SecureQueue::operator=(const SecureQueue& input) 00105 { 00106 destroy(); 00107 head = tail = new SecureQueueNode; 00108 SecureQueueNode* temp = input.head; 00109 while(temp) 00110 { 00111 write(&temp->buffer[temp->start], temp->end - temp->start); 00112 temp = temp->next; 00113 } 00114 return (*this); 00115 } 00116 00117 /* 00118 * Add some bytes to the queue 00119 */ 00120 void SecureQueue::write(const byte input[], size_t length) 00121 { 00122 if(!head) 00123 head = tail = new SecureQueueNode; 00124 while(length) 00125 { 00126 const size_t n = tail->write(input, length); 00127 input += n; 00128 length -= n; 00129 if(length) 00130 { 00131 tail->next = new SecureQueueNode; 00132 tail = tail->next; 00133 } 00134 } 00135 } 00136 00137 /* 00138 * Read some bytes from the queue 00139 */ 00140 size_t SecureQueue::read(byte output[], size_t length) 00141 { 00142 size_t got = 0; 00143 while(length && head) 00144 { 00145 const size_t n = head->read(output, length); 00146 output += n; 00147 got += n; 00148 length -= n; 00149 if(head->size() == 0) 00150 { 00151 SecureQueueNode* holder = head->next; 00152 delete head; 00153 head = holder; 00154 } 00155 } 00156 bytes_read += got; 00157 return got; 00158 } 00159 00160 /* 00161 * Read data, but do not remove it from queue 00162 */ 00163 size_t SecureQueue::peek(byte output[], size_t length, size_t offset) const 00164 { 00165 SecureQueueNode* current = head; 00166 00167 while(offset && current) 00168 { 00169 if(offset >= current->size()) 00170 { 00171 offset -= current->size(); 00172 current = current->next; 00173 } 00174 else 00175 break; 00176 } 00177 00178 size_t got = 0; 00179 while(length && current) 00180 { 00181 const size_t n = current->peek(output, length, offset); 00182 offset = 0; 00183 output += n; 00184 got += n; 00185 length -= n; 00186 current = current->next; 00187 } 00188 return got; 00189 } 00190 00191 /** 00192 * Return how many bytes have been read so far. 00193 */ 00194 size_t SecureQueue::get_bytes_read() const 00195 { 00196 return bytes_read; 00197 } 00198 00199 /* 00200 * Return how many bytes the queue holds 00201 */ 00202 size_t SecureQueue::size() const 00203 { 00204 SecureQueueNode* current = head; 00205 size_t count = 0; 00206 00207 while(current) 00208 { 00209 count += current->size(); 00210 current = current->next; 00211 } 00212 return count; 00213 } 00214 00215 /* 00216 * Test if the queue has any data in it 00217 */ 00218 bool SecureQueue::end_of_data() const 00219 { 00220 return (size() == 0); 00221 } 00222 00223 bool SecureQueue::empty() const 00224 { 00225 return (size() == 0); 00226 } 00227 00228 }