1// channels.cpp - written and placed in the public domain by Wei Dai
2
3#include "pch.h"
4
5#ifndef CRYPTOPP_IMPORTS
6
7#include "channels.h"
8
9NAMESPACE_BEGIN(CryptoPP)
10USING_NAMESPACE(std)
11
12#if 0
13void MessageSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &channel)
14{
15	m_defaultRoutes.push_back(Route(&destination, channel));
16}
17
18void MessageSwitch::AddRoute(unsigned int begin, unsigned int end, BufferedTransformation &destination, const std::string &channel)
19{
20	RangeRoute route(begin, end, Route(&destination, channel));
21	RouteList::iterator it = upper_bound(m_routes.begin(), m_routes.end(), route);
22	m_routes.insert(it, route);
23}
24
25/*
26class MessageRouteIterator
27{
28public:
29	typedef MessageSwitch::RouteList::const_iterator RouteIterator;
30	typedef MessageSwitch::DefaultRouteList::const_iterator DefaultIterator;
31
32	bool m_useDefault;
33	RouteIterator m_itRouteCurrent, m_itRouteEnd;
34	DefaultIterator m_itDefaultCurrent, m_itDefaultEnd;
35
36	MessageRouteIterator(MessageSwitch &ms, const std::string &channel)
37		: m_channel(channel)
38	{
39		pair<MapIterator, MapIterator> range = cs.m_routeMap.equal_range(channel);
40		if (range.first == range.second)
41		{
42			m_useDefault = true;
43			m_itListCurrent = cs.m_defaultRoutes.begin();
44			m_itListEnd = cs.m_defaultRoutes.end();
45		}
46		else
47		{
48			m_useDefault = false;
49			m_itMapCurrent = range.first;
50			m_itMapEnd = range.second;
51		}
52	}
53
54	bool End() const
55	{
56		return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
57	}
58
59	void Next()
60	{
61		if (m_useDefault)
62			++m_itListCurrent;
63		else
64			++m_itMapCurrent;
65	}
66
67	BufferedTransformation & Destination()
68	{
69		return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
70	}
71
72	const std::string & Message()
73	{
74		if (m_useDefault)
75			return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
76		else
77			return m_itMapCurrent->second.second;
78	}
79};
80
81void MessageSwitch::Put(byte inByte);
82void MessageSwitch::Put(const byte *inString, unsigned int length);
83
84void MessageSwitch::Flush(bool completeFlush, int propagation=-1);
85void MessageSwitch::MessageEnd(int propagation=-1);
86void MessageSwitch::PutMessageEnd(const byte *inString, unsigned int length, int propagation=-1);
87void MessageSwitch::MessageSeriesEnd(int propagation=-1);
88*/
89#endif
90
91
92//
93// ChannelRouteIterator
94//////////////////////////
95
96void ChannelRouteIterator::Reset(const std::string &channel)
97{
98	m_channel = channel;
99	pair<MapIterator, MapIterator> range = m_cs.m_routeMap.equal_range(channel);
100	if (range.first == range.second)
101	{
102		m_useDefault = true;
103		m_itListCurrent = m_cs.m_defaultRoutes.begin();
104		m_itListEnd = m_cs.m_defaultRoutes.end();
105	}
106	else
107	{
108		m_useDefault = false;
109		m_itMapCurrent = range.first;
110		m_itMapEnd = range.second;
111	}
112}
113
114bool ChannelRouteIterator::End() const
115{
116	return m_useDefault ? m_itListCurrent == m_itListEnd : m_itMapCurrent == m_itMapEnd;
117}
118
119void ChannelRouteIterator::Next()
120{
121	if (m_useDefault)
122		++m_itListCurrent;
123	else
124		++m_itMapCurrent;
125}
126
127BufferedTransformation & ChannelRouteIterator::Destination()
128{
129	return m_useDefault ? *m_itListCurrent->first : *m_itMapCurrent->second.first;
130}
131
132const std::string & ChannelRouteIterator::Channel()
133{
134	if (m_useDefault)
135		return m_itListCurrent->second.get() ? *m_itListCurrent->second.get() : m_channel;
136	else
137		return m_itMapCurrent->second.second;
138}
139
140
141//
142// ChannelSwitch
143///////////////////
144
145size_t ChannelSwitch::ChannelPut2(const std::string &channel, const byte *begin, size_t length, int messageEnd, bool blocking)
146{
147	if (m_blocked)
148	{
149		m_blocked = false;
150		goto WasBlocked;
151	}
152
153	m_it.Reset(channel);
154
155	while (!m_it.End())
156	{
157WasBlocked:
158		if (m_it.Destination().ChannelPut2(m_it.Channel(), begin, length, messageEnd, blocking))
159		{
160			m_blocked = true;
161			return 1;
162		}
163
164		m_it.Next();
165	}
166
167	return 0;
168}
169
170void ChannelSwitch::IsolatedInitialize(const NameValuePairs &parameters/* =g_nullNameValuePairs */)
171{
172	m_routeMap.clear();
173	m_defaultRoutes.clear();
174	m_blocked = false;
175}
176
177bool ChannelSwitch::ChannelFlush(const std::string &channel, bool completeFlush, int propagation, bool blocking)
178{
179	if (m_blocked)
180	{
181		m_blocked = false;
182		goto WasBlocked;
183	}
184
185	m_it.Reset(channel);
186
187	while (!m_it.End())
188	{
189	  WasBlocked:
190		if (m_it.Destination().ChannelFlush(m_it.Channel(), completeFlush, propagation, blocking))
191		{
192			m_blocked = true;
193			return true;
194		}
195
196		m_it.Next();
197	}
198
199	return false;
200}
201
202bool ChannelSwitch::ChannelMessageSeriesEnd(const std::string &channel, int propagation, bool blocking)
203{
204	if (m_blocked)
205	{
206		m_blocked = false;
207		goto WasBlocked;
208	}
209
210	m_it.Reset(channel);
211
212	while (!m_it.End())
213	{
214	  WasBlocked:
215		if (m_it.Destination().ChannelMessageSeriesEnd(m_it.Channel(), propagation))
216		{
217			m_blocked = true;
218			return true;
219		}
220
221		m_it.Next();
222	}
223
224	return false;
225}
226
227byte * ChannelSwitch::ChannelCreatePutSpace(const std::string &channel, size_t &size)
228{
229	m_it.Reset(channel);
230	if (!m_it.End())
231	{
232		BufferedTransformation &target = m_it.Destination();
233		const std::string &channel = m_it.Channel();
234		m_it.Next();
235		if (m_it.End())	// there is only one target channel
236			return target.ChannelCreatePutSpace(channel, size);
237	}
238	size = 0;
239	return NULL;
240}
241
242size_t ChannelSwitch::ChannelPutModifiable2(const std::string &channel, byte *inString, size_t length, int messageEnd, bool blocking)
243{
244	ChannelRouteIterator it(*this);
245	it.Reset(channel);
246
247	if (!it.End())
248	{
249		BufferedTransformation &target = it.Destination();
250		const std::string &targetChannel = it.Channel();
251		it.Next();
252		if (it.End())	// there is only one target channel
253			return target.ChannelPutModifiable2(targetChannel, inString, length, messageEnd, blocking);
254	}
255
256	return ChannelPut2(channel, inString, length, messageEnd, blocking);
257}
258
259void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination)
260{
261	m_defaultRoutes.push_back(DefaultRoute(&destination, value_ptr<std::string>(NULL)));
262}
263
264void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination)
265{
266	for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
267		if (it->first == &destination && !it->second.get())
268		{
269			m_defaultRoutes.erase(it);
270			break;
271		}
272}
273
274void ChannelSwitch::AddDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
275{
276	m_defaultRoutes.push_back(DefaultRoute(&destination, outChannel));
277}
278
279void ChannelSwitch::RemoveDefaultRoute(BufferedTransformation &destination, const std::string &outChannel)
280{
281	for (DefaultRouteList::iterator it = m_defaultRoutes.begin(); it != m_defaultRoutes.end(); ++it)
282		if (it->first == &destination && (it->second.get() && *it->second == outChannel))
283		{
284			m_defaultRoutes.erase(it);
285			break;
286		}
287}
288
289void ChannelSwitch::AddRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
290{
291	m_routeMap.insert(RouteMap::value_type(inChannel, Route(&destination, outChannel)));
292}
293
294void ChannelSwitch::RemoveRoute(const std::string &inChannel, BufferedTransformation &destination, const std::string &outChannel)
295{
296	typedef ChannelSwitch::RouteMap::iterator MapIterator;
297	pair<MapIterator, MapIterator> range = m_routeMap.equal_range(inChannel);
298
299	for (MapIterator it = range.first; it != range.second; ++it)
300		if (it->second.first == &destination && it->second.second == outChannel)
301		{
302			m_routeMap.erase(it);
303			break;
304		}
305}
306
307NAMESPACE_END
308
309#endif
310