1// mqueue.cpp - written and placed in the public domain by Wei Dai 2 3#include "pch.h" 4 5#ifndef CRYPTOPP_IMPORTS 6 7#include "mqueue.h" 8 9NAMESPACE_BEGIN(CryptoPP) 10 11MessageQueue::MessageQueue(unsigned int nodeSize) 12 : m_queue(nodeSize), m_lengths(1, 0U), m_messageCounts(1, 0U) 13{ 14} 15 16size_t MessageQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const 17{ 18 if (begin >= MaxRetrievable()) 19 return 0; 20 21 return m_queue.CopyRangeTo2(target, begin, STDMIN(MaxRetrievable(), end), channel, blocking); 22} 23 24size_t MessageQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking) 25{ 26 transferBytes = STDMIN(MaxRetrievable(), transferBytes); 27 size_t blockedBytes = m_queue.TransferTo2(target, transferBytes, channel, blocking); 28 m_lengths.front() -= transferBytes; 29 return blockedBytes; 30} 31 32bool MessageQueue::GetNextMessage() 33{ 34 if (NumberOfMessages() > 0 && !AnyRetrievable()) 35 { 36 m_lengths.pop_front(); 37 if (m_messageCounts[0] == 0 && m_messageCounts.size() > 1) 38 m_messageCounts.pop_front(); 39 return true; 40 } 41 else 42 return false; 43} 44 45unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const 46{ 47 ByteQueue::Walker walker(m_queue); 48 std::deque<lword>::const_iterator it = m_lengths.begin(); 49 unsigned int i; 50 for (i=0; i<count && it != --m_lengths.end(); ++i, ++it) 51 { 52 walker.TransferTo(target, *it, channel); 53 if (GetAutoSignalPropagation()) 54 target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1); 55 } 56 return i; 57} 58 59void MessageQueue::swap(MessageQueue &rhs) 60{ 61 m_queue.swap(rhs.m_queue); 62 m_lengths.swap(rhs.m_lengths); 63} 64 65const byte * MessageQueue::Spy(size_t &contiguousSize) const 66{ 67 const byte *result = m_queue.Spy(contiguousSize); 68 contiguousSize = UnsignedMin(contiguousSize, MaxRetrievable()); 69 return result; 70} 71 72// ************************************************************* 73 74unsigned int EqualityComparisonFilter::MapChannel(const std::string &channel) const 75{ 76 if (channel == m_firstChannel) 77 return 0; 78 else if (channel == m_secondChannel) 79 return 1; 80 else 81 return 2; 82} 83 84size_t EqualityComparisonFilter::ChannelPut2(const std::string &channel, const byte *inString, size_t length, int messageEnd, bool blocking) 85{ 86 if (!blocking) 87 throw BlockingInputOnly("EqualityComparisonFilter"); 88 89 unsigned int i = MapChannel(channel); 90 91 if (i == 2) 92 return Output(3, inString, length, messageEnd, blocking, channel); 93 else if (m_mismatchDetected) 94 return 0; 95 else 96 { 97 MessageQueue &q1 = m_q[i], &q2 = m_q[1-i]; 98 99 if (q2.AnyMessages() && q2.MaxRetrievable() < length) 100 goto mismatch; 101 102 while (length > 0 && q2.AnyRetrievable()) 103 { 104 size_t len = length; 105 const byte *data = q2.Spy(len); 106 len = STDMIN(len, length); 107 if (memcmp(inString, data, len) != 0) 108 goto mismatch; 109 inString += len; 110 length -= len; 111 q2.Skip(len); 112 } 113 114 q1.Put(inString, length); 115 116 if (messageEnd) 117 { 118 if (q2.AnyRetrievable()) 119 goto mismatch; 120 else if (q2.AnyMessages()) 121 q2.GetNextMessage(); 122 else if (q2.NumberOfMessageSeries() > 0) 123 goto mismatch; 124 else 125 q1.MessageEnd(); 126 } 127 128 return 0; 129 130mismatch: 131 return HandleMismatchDetected(blocking); 132 } 133} 134 135bool EqualityComparisonFilter::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking) 136{ 137 unsigned int i = MapChannel(channel); 138 139 if (i == 2) 140 { 141 OutputMessageSeriesEnd(4, propagation, blocking, channel); 142 return false; 143 } 144 else if (m_mismatchDetected) 145 return false; 146 else 147 { 148 MessageQueue &q1 = m_q[i], &q2 = m_q[1-i]; 149 150 if (q2.AnyRetrievable() || q2.AnyMessages()) 151 goto mismatch; 152 else if (q2.NumberOfMessageSeries() > 0) 153 return Output(2, (const byte *)"\1", 1, 0, blocking) != 0; 154 else 155 q1.MessageSeriesEnd(); 156 157 return false; 158 159mismatch: 160 return HandleMismatchDetected(blocking); 161 } 162} 163 164bool EqualityComparisonFilter::HandleMismatchDetected(bool blocking) 165{ 166 m_mismatchDetected = true; 167 if (m_throwIfNotEqual) 168 throw MismatchDetected(); 169 return Output(1, (const byte *)"\0", 1, 0, blocking) != 0; 170} 171 172NAMESPACE_END 173 174#endif 175