2 * Copyright (c) 2011 Sveriges Television AB <info@casparcg.com>
\r
4 * This file is part of CasparCG (www.casparcg.com).
\r
6 * CasparCG is free software: you can redistribute it and/or modify
\r
7 * it under the terms of the GNU General Public License as published by
\r
8 * the Free Software Foundation, either version 3 of the License, or
\r
9 * (at your option) any later version.
\r
11 * CasparCG is distributed in the hope that it will be useful,
\r
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
\r
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
\r
14 * GNU General Public License for more details.
\r
16 * You should have received a copy of the GNU General Public License
\r
17 * along with CasparCG. If not, see <http://www.gnu.org/licenses/>.
\r
19 * Author: Helge Norberg, helge.norberg@svt.se
\r
24 #include <boost/algorithm/string/split.hpp>
\r
26 #include "protocol_strategy.h"
\r
27 #include "ProtocolStrategy.h"
\r
29 namespace caspar { namespace IO {
\r
32 * A protocol strategy factory adapter for converting incoming data from a
\r
33 * specific codepage to utf-16. The client_connection will do the reversed
\r
36 * The adapter is not safe if the codepage contains multibyte-characters and
\r
37 * the data is chunked with potentially incomplete characters, therefore it
\r
38 * must be wrapped in an adapter providing complete chunks like
\r
39 * delimiter_based_chunking_strategy_factory.
\r
41 class to_unicode_adapter_factory : public protocol_strategy_factory<char>
\r
43 std::string codepage_;
\r
44 protocol_strategy_factory<wchar_t>::ptr unicode_strategy_factory_;
\r
46 to_unicode_adapter_factory(
\r
47 const std::string& codepage,
\r
48 const protocol_strategy_factory<wchar_t>::ptr& unicode_strategy_factory);
\r
50 virtual protocol_strategy<char>::ptr create(
\r
51 const client_connection<char>::ptr& client_connection);
\r
55 * Protocol strategy adapter for ensuring that only complete chunks or
\r
56 * "packets" are delivered to the wrapped strategy. The chunks are determined
\r
57 * by a given delimiter.
\r
59 template<class CharT>
\r
60 class delimiter_based_chunking_strategy : public protocol_strategy<CharT>
\r
62 std::basic_string<CharT> delimiter_;
\r
63 std::basic_string<CharT> input_;
\r
64 typename protocol_strategy<CharT>::ptr strategy_;
\r
66 delimiter_based_chunking_strategy(
\r
67 const std::basic_string<CharT>& delimiter,
\r
68 const typename protocol_strategy<CharT>::ptr& strategy)
\r
69 : delimiter_(delimiter)
\r
70 , strategy_(strategy)
\r
74 virtual void parse(const std::basic_string<CharT>& data)
\r
78 //boost::iter_split(split, input_, boost::algorithm::first_finder(delimiter_)) was painfully slow in debug-build
\r
80 auto delim_pos = input_.find(delimiter_);
\r
81 while(delim_pos != std::string::npos)
\r
83 strategy_->parse(input_.substr(0, delim_pos));
\r
85 input_ = std::move(input_.substr(delim_pos+delimiter_.size()));
\r
86 delim_pos = input_.find_first_of(delimiter_);
\r
91 template<class CharT>
\r
92 class delimiter_based_chunking_strategy_factory
\r
93 : public protocol_strategy_factory<CharT>
\r
95 std::basic_string<CharT> delimiter_;
\r
96 typename protocol_strategy_factory<CharT>::ptr strategy_factory_;
\r
98 delimiter_based_chunking_strategy_factory(
\r
99 const std::basic_string<CharT>& delimiter,
\r
100 const typename protocol_strategy_factory<CharT>::ptr& strategy_factory)
\r
101 : delimiter_(delimiter)
\r
102 , strategy_factory_(strategy_factory)
\r
106 virtual typename protocol_strategy<CharT>::ptr create(
\r
107 const typename client_connection<CharT>::ptr& client_connection)
\r
109 return spl::make_shared<delimiter_based_chunking_strategy<CharT>>(
\r
110 delimiter_, strategy_factory_->create(client_connection));
\r
115 * Adapts an IProtocolStrategy to be used as a
\r
116 * protocol_strategy_factory<wchar_t>.
\r
118 * Use wrap_legacy_protocol() to wrap it as a protocol_strategy_factory<char>
\r
119 * for use directly by the async event server.
\r
121 class legacy_strategy_adapter_factory
\r
122 : public protocol_strategy_factory<wchar_t>
\r
124 ProtocolStrategyPtr strategy_;
\r
126 legacy_strategy_adapter_factory(const ProtocolStrategyPtr& strategy);
\r
128 virtual protocol_strategy<wchar_t>::ptr create(
\r
129 const client_connection<wchar_t>::ptr& client_connection);
\r
133 * Wraps an IProtocolStrategy in a legacy_strategy_adapter_factory, wrapped in
\r
134 * a to_unicode_adapter_factory (using the codepage reported by the
\r
135 * IProtocolStrategy) wrapped in a delimiter_based_chunking_strategy_factory
\r
136 * with the given delimiter string.
\r
138 * @param delimiter The delimiter to use to separate messages.
\r
139 * @param strategy The legacy protocol strategy (the same instance will serve
\r
140 * all connections).
\r
142 * @return the adapted strategy.
\r
144 protocol_strategy_factory<char>::ptr wrap_legacy_protocol(
\r
145 const std::string& delimiter,
\r
146 const ProtocolStrategyPtr& strategy);
\r