- Main Page
- Namespaces
- Classes
- Files

# mqueue.cpp

    00001 // mqueue.cpp - written and placed in the public domain by Wei Dai
    00002
    00003 #include "pch.h"
    00004
    00005 #ifndef CRYPTOPP_IMPORTS
    00006
    00007 #include "mqueue.h"
    00008
    00009 NAMESPACE_BEGIN(CryptoPP)
    00010
    00011 MessageQueue::MessageQueue(unsigned int nodeSize)
    00012         : m_queue(nodeSize), m_lengths(1, 0U), m_messageCounts(1, 0U)
    00013 {
    00014 }
    00015
    00016 size_t MessageQueue::CopyRangeTo2(BufferedTransformation &target, lword &begin, lword end, const std::string &channel, bool blocking) const
    00017 {
    00018         if (begin >= MaxRetrievable())
    00019                 return 0;
    00020
    00021         return m_queue.CopyRangeTo2(target, begin, STDMIN(MaxRetrievable(), end), channel, blocking);
    00022 }
    00023
    00024 size_t MessageQueue::TransferTo2(BufferedTransformation &target, lword &transferBytes, const std::string &channel, bool blocking)
    00025 {
    00026         transferBytes = STDMIN(MaxRetrievable(), transferBytes);
    00027         size_t blockedBytes = m_queue.TransferTo2(target, transferBytes, channel, blocking);
    00028         m_lengths.front() -= transferBytes;
    00029         return blockedBytes;
    00030 }
    00031
    00032 bool MessageQueue::GetNextMessage()
    00033 {
    00034         if (NumberOfMessages() > 0 && !AnyRetrievable())
    00035         {
    00036                 m_lengths.pop_front();
    00037                 if (m_messageCounts[0] == 0 && m_messageCounts.size() > 1)
    00038                         m_messageCounts.pop_front();
    00039                 return true;
    00040         }
    00041         else
    00042                 return false;
    00043 }
    00044
    00045 unsigned int MessageQueue::CopyMessagesTo(BufferedTransformation &target, unsigned int count, const std::string &channel) const
    00046 {
    00047         ByteQueue::Walker walker(m_queue);
    00048         std::deque<lword>::const_iterator it = m_lengths.begin();
    00049         unsigned int i;
    00050         for (i=0; i<count && it != --m_lengths.end(); ++i, ++it)
    00051         {
    00052                 walker.TransferTo(target, *it, channel);
    00053                 if (GetAutoSignalPropagation())
    00054                         target.ChannelMessageEnd(channel, GetAutoSignalPropagation()-1);
    00055         }
    00056         return i;
    00057 }
    00058
    00059 void MessageQueue::swap(MessageQueue &rhs)
    00060 {
    00061         m_queue.swap(rhs.m_queue);
    00062         m_lengths.swap(rhs.m_lengths);
    00063 }
    00064
    00065 const byte * MessageQueue::Spy(size_t &contiguousSize) const
    00066 {
    00067         const byte *result = m_queue.Spy(contiguousSize);
    00068         contiguousSize = UnsignedMin(contiguousSize, MaxRetrievable());
    00069         return result;
    00070 }
    00071
    00072 // *************************************************************
    00073
    00074 unsigned int EqualityComparisonFilter::MapChannel(const std::string &channel) const
    00075 {
    00076         if (channel == m_firstChannel)
    00077                 return 0;
    00078         else if (channel == m_secondChannel)
    00079                 return 1;
    00080         else
    00081                 return 2;
    00082 }
    00083
    00084 size_t EqualityComparisonFilter::ChannelPut2(const std::string &channel, const byte *inString, size_t length, int messageEnd, bool blocking)
    00085 {
    00086         if (!blocking)
    00087                 throw BlockingInputOnly("EqualityComparisonFilter");
    00088
    00089         unsigned int i = MapChannel(channel);
    00090
    00091         if (i == 2)
    00092                 return Output(3, inString, length, messageEnd, blocking, channel);
    00093         else if (m_mismatchDetected)
    00094                 return 0;
    00095         else
    00096         {
    00097                 MessageQueue &q1 = m_q[i], &q2 = m_q[1-i];
    00098
    00099                 if (q2.AnyMessages() && q2.MaxRetrievable() < length)
    00100                         goto mismatch;
    00101
    00102                 while (length > 0 && q2.AnyRetrievable())
    00103                 {
    00104                         size_t len = length;
    00105                         const byte *data = q2.Spy(len);
    00106                         len = STDMIN(len, length);
    00107                         if (memcmp(inString, data, len) != 0)
    00108                                 goto mismatch;
    00109                         inString += len;
    00110                         length -= len;
    00111                         q2.Skip(len);
    00112                 }
    00113
    00114                 q1.Put(inString, length);
    00115
    00116                 if (messageEnd)
    00117                 {
    00118                         if (q2.AnyRetrievable())
    00119                                 goto mismatch;
    00120                         else if (q2.AnyMessages())
    00121                                 q2.GetNextMessage();
    00122                         else if (q2.NumberOfMessageSeries() > 0)
    00123                                 goto mismatch;
    00124                         else
    00125                                 q1.MessageEnd();
    00126                 }
    00127
    00128                 return 0;
    00129
    00130 mismatch:
    00131                 return HandleMismatchDetected(blocking);
    00132         }
    00133 }
    00134
    00135 bool EqualityComparisonFilter::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
    00136 {
    00137         unsigned int i = MapChannel(channel);
    00138
    00139         if (i == 2)
    00140         {
    00141                 OutputMessageSeriesEnd(4, propagation, blocking, channel);
    00142                 return false;
    00143         }
    00144         else if (m_mismatchDetected)
    00145                 return false;
    00146         else
    00147         {
    00148                 MessageQueue &q1 = m_q[i], &q2 = m_q[1-i];
    00149
    00150                 if (q2.AnyRetrievable() || q2.AnyMessages())
    00151                         goto mismatch;
    00152                 else if (q2.NumberOfMessageSeries() > 0)
    00153                         return Output(2, (const byte *)"\1", 1, 0, blocking) != 0;
    00154                 else
    00155                         q1.MessageSeriesEnd();
    00156
    00157                 return false;
    00158
    00159 mismatch:
    00160                 return HandleMismatchDetected(blocking);
    00161         }
    00162 }
    00163
    00164 bool EqualityComparisonFilter::HandleMismatchDetected(bool blocking)
    00165 {
    00166         m_mismatchDetected = true;
    00167         if (m_throwIfNotEqual)
    00168                 throw MismatchDetected();
    00169         return Output(1, (const byte *)"\0", 1, 0, blocking) != 0;
    00170 }
    00171
    00172 NAMESPACE_END
    00173
    00174 #endif