Botan  1.11.15
src/lib/filters/secqueue.cpp
Go to the documentation of this file.
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 }