00001
00002
00003 #include "pch.h"
00004
00005 #ifndef CRYPTOPP_IMPORTS
00006
00007 #include "queue.h"
00008 #include "filters.h"
00009
00010 NAMESPACE_BEGIN(CryptoPP)
00011
00012 static const unsigned int s_maxAutoNodeSize = 16*1024;
00013
00014
00015 class ByteQueueNode
00016 {
00017 public:
00018 ByteQueueNode(size_t maxSize)
00019 : buf(maxSize)
00020 {
00021 m_head = m_tail = 0;
00022 next = 0;
00023 }
00024
00025 inline size_t MaxSize() const {return buf.size();}
00026
00027 inline size_t CurrentSize() const
00028 {
00029 return m_tail-m_head;
00030 }
00031
00032 inline bool UsedUp() const
00033 {
00034 return (m_head==MaxSize());
00035 }
00036
00037 inline void Clear()
00038 {
00039 m_head = m_tail = 0;
00040 }
00041
00042 inline size_t Put(const byte *begin, size_t length)
00043 {
00044
00045 if (!begin || !length) return length;
00046 size_t l = STDMIN(length, MaxSize()-m_tail);
00047 if (buf+m_tail != begin)
00048 memcpy(buf+m_tail, begin, l);
00049 m_tail += l;
00050 return l;
00051 }
00052
00053 inline size_t Peek(byte &outByte) const
00054 {
00055 if (m_tail==m_head)
00056 return 0;
00057
00058 outByte=buf[m_head];
00059 return 1;
00060 }
00061
00062 inline size_t Peek(byte *target, size_t copyMax) const
00063 {
00064 size_t len = STDMIN(copyMax, m_tail-m_head);
00065 memcpy(target, buf+m_head, len);
00066 return len;
00067 }
00068
00069 inline size_t CopyTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL) const
00070 {
00071 size_t len = m_tail-m_head;
00072 target.ChannelPut(channel, buf+m_head, len);
00073 return len;
00074 }
00075
00076 inline size_t CopyTo(BufferedTransformation &target, size_t copyMax, const std::string &channel=DEFAULT_CHANNEL) const
00077 {
00078 size_t len = STDMIN(copyMax, m_tail-m_head);
00079 target.ChannelPut(channel, buf+m_head, len);
00080 return len;
00081 }
00082
00083 inline size_t Get(byte &outByte)
00084 {
00085 size_t len = Peek(outByte);
00086 m_head += len;
00087 return len;
00088 }
00089
00090 inline size_t Get(byte *outString, size_t getMax)
00091 {
00092 size_t len = Peek(outString, getMax);
00093 m_head += len;
00094 return len;
00095 }
00096
00097 inline size_t TransferTo(BufferedTransformation &target, const std::string &channel=DEFAULT_CHANNEL)
00098 {
00099 size_t len = m_tail-m_head;
00100 target.ChannelPutModifiable(channel, buf+m_head, len);
00101 m_head = m_tail;
00102 return len;
00103 }
00104
00105 inline size_t TransferTo(BufferedTransformation &target, lword transferMax, const std::string &channel=DEFAULT_CHANNEL)
00106 {
00107 size_t len = UnsignedMin(m_tail-m_head, transferMax);
00108 target.ChannelPutModifiable(channel, buf+m_head, len);
00109 m_head += len;
00110 return len;
00111 }
00112
00113 inline size_t Skip(size_t skipMax)
00114 {
00115 size_t len = STDMIN(skipMax, m_tail-m_head);
00116 m_head += len;
00117 return len;
00118 }
00119
00120 inline byte operator[](size_t i) const
00121 {
00122 return buf[m_head+i];
00123 }
00124
00125 ByteQueueNode *next;
00126
00127 SecByteBlock buf;
00128 size_t m_head, m_tail;
00129 };
00130
00131
00132
00133 ByteQueue::ByteQueue(size_t nodeSize)
00134 : Bufferless<BufferedTransformation>(), m_autoNodeSize(!nodeSize), m_nodeSize(nodeSize)
00135 , m_head(NULL), m_tail(NULL), m_lazyString(NULL), m_lazyLength(0), m_lazyStringModifiable(false)
00136 {
00137 SetNodeSize(nodeSize);
00138 m_head = m_tail = new ByteQueueNode(m_nodeSize);
00139 }
00140
00141 void ByteQueue::SetNodeSize(size_t nodeSize)
00142 {
00143 m_autoNodeSize = !nodeSize;
00144 m_nodeSize = m_autoNodeSize ? 256 : nodeSize;
00145 }
00146
00147 ByteQueue::ByteQueue(const ByteQueue ©)
00148 : Bufferless<BufferedTransformation>(copy), m_lazyString(NULL), m_lazyLength(0)
00149 {
00150 CopyFrom(copy);
00151 }
00152
00153 void ByteQueue::CopyFrom(const ByteQueue ©)
00154 {
00155 m_lazyLength = 0;
00156 m_autoNodeSize = copy.m_autoNodeSize;
00157 m_nodeSize = copy.m_nodeSize;
00158 m_head = m_tail = new ByteQueueNode(*copy.m_head);
00159
00160 for (ByteQueueNode *current=copy.m_head->next; current; current=current->next)
00161 {
00162 m_tail->next = new ByteQueueNode(*current);
00163 m_tail = m_tail->next;
00164 }
00165
00166 m_tail->next = NULL;
00167
00168 Put(copy.m_lazyString, copy.m_lazyLength);
00169 }
00170
00171 ByteQueue::~ByteQueue()
00172 {
00173 Destroy();
00174 }
00175
00176 void ByteQueue::Destroy()
00177 {
00178 for (ByteQueueNode *next, *current=m_head; current; current=next)
00179 {
00180 next=current->next;
00181 delete current;
00182 }
00183 }
00184
00185 void ByteQueue::IsolatedInitialize(const NameValuePairs ¶meters)
00186 {
00187 m_nodeSize = parameters.GetIntValueWithDefault("NodeSize", 256);
00188 Clear();
00189 }
00190
00191 lword ByteQueue::CurrentSize() const
00192 {
00193 lword size=0;
00194
00195 for (ByteQueueNode *current=m_head; current; current=current->next)
00196 size += current->CurrentSize();
00197
00198 return size + m_lazyLength;
00199 }
00200
00201 bool ByteQueue::IsEmpty() const
00202 {
00203 return m_head==m_tail && m_head->CurrentSize()==0 && m_lazyLength==0;
00204 }
00205
00206 void ByteQueue::Clear()
00207 {
00208 for (ByteQueueNode *next, *current=m_head->next; current; current=next)
00209 {
00210 next=current->next;
00211 delete current;
00212 }
00213
00214 m_tail = m_head;
00215 m_head->Clear();
00216 m_head->next = NULL;
00217 m_lazyLength = 0;
00218 }
00219
00220 size_t ByteQueue::Put2(const byte *inString, size_t length, int messageEnd, bool blocking)
00221 {
00222 CRYPTOPP_UNUSED(messageEnd), CRYPTOPP_UNUSED(blocking);
00223
00224 if (m_lazyLength > 0)
00225 FinalizeLazyPut();
00226
00227 size_t len;
00228 while ((len=m_tail->Put(inString, length)) < length)
00229 {
00230 inString += len;
00231 length -= len;
00232 if (m_autoNodeSize && m_nodeSize < s_maxAutoNodeSize)
00233 do
00234 {
00235 m_nodeSize *= 2;
00236 }
00237 while (m_nodeSize < length && m_nodeSize < s_maxAutoNodeSize);
00238 m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, length));
00239 m_tail = m_tail->next;
00240 }
00241
00242 return 0;
00243 }
00244
00245 void ByteQueue::CleanupUsedNodes()
00246 {
00247
00248 while (m_head && m_head != m_tail && m_head->UsedUp())
00249 {
00250 ByteQueueNode *temp=m_head;
00251 m_head=m_head->next;
00252 delete temp;
00253 }
00254
00255
00256 if (m_head && m_head->CurrentSize() == 0)
00257 m_head->Clear();
00258 }
00259
00260 void ByteQueue::LazyPut(const byte *inString, size_t size)
00261 {
00262 if (m_lazyLength > 0)
00263 FinalizeLazyPut();
00264
00265 if (inString == m_tail->buf+m_tail->m_tail)
00266 Put(inString, size);
00267 else
00268 {
00269 m_lazyString = const_cast<byte *>(inString);
00270 m_lazyLength = size;
00271 m_lazyStringModifiable = false;
00272 }
00273 }
00274
00275 void ByteQueue::LazyPutModifiable(byte *inString, size_t size)
00276 {
00277 if (m_lazyLength > 0)
00278 FinalizeLazyPut();
00279 m_lazyString = inString;
00280 m_lazyLength = size;
00281 m_lazyStringModifiable = true;
00282 }
00283
00284 void ByteQueue::UndoLazyPut(size_t size)
00285 {
00286 if (m_lazyLength < size)
00287 throw InvalidArgument("ByteQueue: size specified for UndoLazyPut is too large");
00288
00289 m_lazyLength -= size;
00290 }
00291
00292 void ByteQueue::FinalizeLazyPut()
00293 {
00294 size_t len = m_lazyLength;
00295 m_lazyLength = 0;
00296 if (len)
00297 Put(m_lazyString, len);
00298 }
00299
00300 size_t ByteQueue::Get(byte &outByte)
00301 {
00302 if (m_head->Get(outByte))
00303 {
00304 if (m_head->UsedUp())
00305 CleanupUsedNodes();
00306 return 1;
00307 }
00308 else if (m_lazyLength > 0)
00309 {
00310 outByte = *m_lazyString++;
00311 m_lazyLength--;
00312 return 1;
00313 }
00314 else
00315 return 0;
00316 }
00317
00318 size_t ByteQueue::Get(byte *outString, size_t getMax)
00319 {
00320 ArraySink sink(outString, getMax);
00321 return (size_t)TransferTo(sink, getMax);
00322 }
00323
00324 size_t ByteQueue::Peek(byte &outByte) const
00325 {
00326 if (m_head->Peek(outByte))
00327 return 1;
00328 else if (m_lazyLength > 0)
00329 {
00330 outByte = *m_lazyString;
00331 return 1;
00332 }
00333 else
00334 return 0;
00335 }
00336
00337 size_t ByteQueue::Peek(byte *outString, size_t peekMax) const
00338 {
00339 ArraySink sink(outString, peekMax);
00340 return (size_t)CopyTo(sink, peekMax);
00341 }
00342
00343 size_t ByteQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
00344 {
00345 if (blocking)
00346 {
00347 lword bytesLeft = transferBytes;
00348 for (ByteQueueNode *current=m_head; bytesLeft && current; current=current->next)
00349 bytesLeft -= current->TransferTo(target, bytesLeft, channel);
00350 CleanupUsedNodes();
00351
00352 size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
00353 if (len)
00354 {
00355 if (m_lazyStringModifiable)
00356 target.ChannelPutModifiable(channel, m_lazyString, len);
00357 else
00358 target.ChannelPut(channel, m_lazyString, len);
00359 m_lazyString += len;
00360 m_lazyLength -= len;
00361 bytesLeft -= len;
00362 }
00363 transferBytes -= bytesLeft;
00364 return 0;
00365 }
00366 else
00367 {
00368 Walker walker(*this);
00369 size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
00370 Skip(transferBytes);
00371 return blockedBytes;
00372 }
00373 }
00374
00375 size_t ByteQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
00376 {
00377 Walker walker(*this);
00378 walker.Skip(begin);
00379 lword transferBytes = end-begin;
00380 size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
00381 begin += transferBytes;
00382 return blockedBytes;
00383 }
00384
00385 void ByteQueue::Unget(byte inByte)
00386 {
00387 Unget(&inByte, 1);
00388 }
00389
00390 void ByteQueue::Unget(const byte *inString, size_t length)
00391 {
00392 size_t len = STDMIN(length, m_head->m_head);
00393 length -= len;
00394 m_head->m_head -= len;
00395 memcpy(m_head->buf + m_head->m_head, inString + length, len);
00396
00397 if (length > 0)
00398 {
00399 ByteQueueNode *newHead = new ByteQueueNode(length);
00400 newHead->next = m_head;
00401 m_head = newHead;
00402 m_head->Put(inString, length);
00403 }
00404 }
00405
00406 const byte * ByteQueue::Spy(size_t &contiguousSize) const
00407 {
00408 contiguousSize = m_head->m_tail - m_head->m_head;
00409 if (contiguousSize == 0 && m_lazyLength > 0)
00410 {
00411 contiguousSize = m_lazyLength;
00412 return m_lazyString;
00413 }
00414 else
00415 return m_head->buf + m_head->m_head;
00416 }
00417
00418 byte * ByteQueue::CreatePutSpace(size_t &size)
00419 {
00420 if (m_lazyLength > 0)
00421 FinalizeLazyPut();
00422
00423 if (m_tail->m_tail == m_tail->MaxSize())
00424 {
00425 m_tail->next = new ByteQueueNode(STDMAX(m_nodeSize, size));
00426 m_tail = m_tail->next;
00427 }
00428
00429 size = m_tail->MaxSize() - m_tail->m_tail;
00430 return m_tail->buf + m_tail->m_tail;
00431 }
00432
00433 ByteQueue & ByteQueue::operator=(const ByteQueue &rhs)
00434 {
00435 Destroy();
00436 CopyFrom(rhs);
00437 return *this;
00438 }
00439
00440 bool ByteQueue::operator==(const ByteQueue &rhs) const
00441 {
00442 const lword currentSize = CurrentSize();
00443
00444 if (currentSize != rhs.CurrentSize())
00445 return false;
00446
00447 Walker walker1(*this), walker2(rhs);
00448 byte b1, b2;
00449
00450 while (walker1.Get(b1) && walker2.Get(b2))
00451 if (b1 != b2)
00452 return false;
00453
00454 return true;
00455 }
00456
00457 byte ByteQueue::operator[](lword i) const
00458 {
00459 for (ByteQueueNode *current=m_head; current; current=current->next)
00460 {
00461 if (i < current->CurrentSize())
00462 return (*current)[(size_t)i];
00463
00464 i -= current->CurrentSize();
00465 }
00466
00467 assert(i < m_lazyLength);
00468 return m_lazyString[i];
00469 }
00470
00471 void ByteQueue::swap(ByteQueue &rhs)
00472 {
00473 std::swap(m_autoNodeSize, rhs.m_autoNodeSize);
00474 std::swap(m_nodeSize, rhs.m_nodeSize);
00475 std::swap(m_head, rhs.m_head);
00476 std::swap(m_tail, rhs.m_tail);
00477 std::swap(m_lazyString, rhs.m_lazyString);
00478 std::swap(m_lazyLength, rhs.m_lazyLength);
00479 std::swap(m_lazyStringModifiable, rhs.m_lazyStringModifiable);
00480 }
00481
00482
00483
00484 void ByteQueue::Walker::IsolatedInitialize(const NameValuePairs ¶meters)
00485 {
00486 CRYPTOPP_UNUSED(parameters);
00487
00488 m_node = m_queue.m_head;
00489 m_position = 0;
00490 m_offset = 0;
00491 m_lazyString = m_queue.m_lazyString;
00492 m_lazyLength = m_queue.m_lazyLength;
00493 }
00494
00495 size_t ByteQueue::Walker::Get(byte &outByte)
00496 {
00497 ArraySink sink(&outByte, 1);
00498 return (size_t)TransferTo(sink, 1);
00499 }
00500
00501 size_t ByteQueue::Walker::Get(byte *outString, size_t getMax)
00502 {
00503 ArraySink sink(outString, getMax);
00504 return (size_t)TransferTo(sink, getMax);
00505 }
00506
00507 size_t ByteQueue::Walker::Peek(byte &outByte) const
00508 {
00509 ArraySink sink(&outByte, 1);
00510 return (size_t)CopyTo(sink, 1);
00511 }
00512
00513 size_t ByteQueue::Walker::Peek(byte *outString, size_t peekMax) const
00514 {
00515 ArraySink sink(outString, peekMax);
00516 return (size_t)CopyTo(sink, peekMax);
00517 }
00518
00519 size_t ByteQueue::Walker::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
00520 {
00521 lword bytesLeft = transferBytes;
00522 size_t blockedBytes = 0;
00523
00524 while (m_node)
00525 {
00526 size_t len = (size_t)STDMIN(bytesLeft, (lword)m_node->CurrentSize()-m_offset);
00527 blockedBytes = target.ChannelPut2(channel, m_node->buf+m_node->m_head+m_offset, len, 0, blocking);
00528
00529 if (blockedBytes)
00530 goto done;
00531
00532 m_position += len;
00533 bytesLeft -= len;
00534
00535 if (!bytesLeft)
00536 {
00537 m_offset += len;
00538 goto done;
00539 }
00540
00541 m_node = m_node->next;
00542 m_offset = 0;
00543 }
00544
00545 if (bytesLeft && m_lazyLength)
00546 {
00547 size_t len = (size_t)STDMIN(bytesLeft, (lword)m_lazyLength);
00548 blockedBytes = target.ChannelPut2(channel, m_lazyString, len, 0, blocking);
00549 if (blockedBytes)
00550 goto done;
00551
00552 m_lazyString += len;
00553 m_lazyLength -= len;
00554 bytesLeft -= len;
00555 }
00556
00557 done:
00558 transferBytes -= bytesLeft;
00559 return blockedBytes;
00560 }
00561
00562 size_t ByteQueue::Walker::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
00563 {
00564 Walker walker(*this);
00565 walker.Skip(begin);
00566 lword transferBytes = end-begin;
00567 size_t blockedBytes = walker.TransferTo2(target, transferBytes, channel, blocking);
00568 begin += transferBytes;
00569 return blockedBytes;
00570 }
00571
00572 NAMESPACE_END
00573
00574 #endif