Line data Source code
1 : /*
2 : * Copyright (c) 2013 Juniper Networks, Inc. All rights reserved.
3 : * Copyright Contributors to the OpenSDN project
4 : */
5 :
6 : #ifndef _SANDESH_PROTOCOL_TXMLPROTOCOL_H_
7 : #define _SANDESH_PROTOCOL_TXMLPROTOCOL_H_ 1
8 :
9 : #include <string.h>
10 : #include "TVirtualProtocol.h"
11 :
12 : #include <boost/shared_ptr.hpp>
13 : #include <boost/tokenizer.hpp>
14 : #include <boost/algorithm/string.hpp>
15 : #include <boost/algorithm/string/replace.hpp>
16 :
17 : namespace contrail { namespace sandesh { namespace protocol {
18 :
19 : /**
20 : * Protocol that prints the payload in XML format.
21 : */
22 : class TXMLProtocol : public TVirtualProtocol<TXMLProtocol> {
23 : private:
24 : enum write_state_t
25 : { UNINIT
26 : , STRUCT
27 : , LIST
28 : , SET
29 : , MAP
30 : , SNDESH
31 : };
32 :
33 : public:
34 : TXMLProtocol(boost::shared_ptr<TTransport> trans)
35 : : TVirtualProtocol<TXMLProtocol>(trans)
36 : , trans_(trans.get())
37 : , string_limit_(DEFAULT_STRING_LIMIT)
38 : , string_prefix_size_(DEFAULT_STRING_PREFIX_SIZE)
39 : , reader_(*trans)
40 : {
41 : write_state_.push_back(UNINIT);
42 : }
43 :
44 : static const int32_t DEFAULT_STRING_LIMIT = 256;
45 : static const int32_t DEFAULT_STRING_PREFIX_SIZE = 16;
46 :
47 : void setStringSizeLimit(int32_t string_limit) {
48 : string_limit_ = string_limit;
49 : }
50 :
51 : void setStringPrefixSize(int32_t string_prefix_size) {
52 : string_prefix_size_ = string_prefix_size;
53 : }
54 :
55 3 : static std::string escapeXMLControlCharsInternal(const std::string& str) {
56 3 : std::string xmlstr;
57 3 : xmlstr.reserve(str.length());
58 3 : for (std::string::const_iterator it = str.begin();
59 476 : it != str.end(); ++it) {
60 473 : switch(*it) {
61 3 : case '&': xmlstr += "&"; break;
62 0 : case '\'': xmlstr += "'"; break;
63 0 : case '<': xmlstr += "<"; break;
64 1 : case '>': xmlstr += ">"; break;
65 469 : default: xmlstr += *it;
66 : }
67 : }
68 3 : return xmlstr;
69 0 : }
70 :
71 169884 : static std::string escapeXMLControlChars(const std::string& str) {
72 169884 : if (strpbrk(str.c_str(), "&'<>") != NULL) {
73 3 : return escapeXMLControlCharsInternal(str);
74 : } else {
75 169881 : return str;
76 : }
77 : }
78 :
79 1232 : static void unescapeXMLControlChars(std::string& str) {
80 1232 : boost::algorithm::replace_all(str, "&", "&");
81 1232 : boost::algorithm::replace_all(str, "'", "\'");
82 1232 : boost::algorithm::replace_all(str, "<", "<");
83 1232 : boost::algorithm::replace_all(str, ">", ">");
84 1232 : }
85 :
86 : /**
87 : * Writing functions
88 : */
89 :
90 : int32_t writeMessageBegin(const std::string& name,
91 : const TMessageType messageType,
92 : const int32_t seqid);
93 :
94 : int32_t writeMessageEnd();
95 :
96 : int32_t writeStructBegin(const char* name);
97 :
98 : int32_t writeStructEnd();
99 :
100 : int32_t writeSandeshBegin(const char* name);
101 :
102 : int32_t writeSandeshEnd();
103 :
104 : int32_t writeContainerElementBegin();
105 :
106 : int32_t writeContainerElementEnd();
107 :
108 : int32_t writeFieldBegin(const char* name,
109 : const TType fieldType,
110 : const int16_t fieldId,
111 : const std::map<std::string, std::string> *const amap = NULL);
112 :
113 : int32_t writeFieldEnd();
114 :
115 : int32_t writeFieldStop();
116 :
117 : int32_t writeMapBegin(const TType keyType,
118 : const TType valType,
119 : const uint32_t size);
120 :
121 : int32_t writeMapEnd();
122 :
123 : int32_t writeListBegin(const TType elemType,
124 : const uint32_t size);
125 :
126 : int32_t writeListEnd();
127 :
128 : int32_t writeSetBegin(const TType elemType,
129 : const uint32_t size);
130 :
131 : int32_t writeSetEnd();
132 :
133 : int32_t writeBool(const bool value);
134 :
135 : int32_t writeByte(const int8_t byte);
136 :
137 : int32_t writeI16(const int16_t i16);
138 :
139 : int32_t writeI32(const int32_t i32);
140 :
141 : int32_t writeI64(const int64_t i64);
142 :
143 : int32_t writeU16(const uint16_t u16);
144 :
145 : int32_t writeU32(const uint32_t u32);
146 :
147 : int32_t writeU64(const uint64_t u64);
148 :
149 : int32_t writeIPV4(const uint32_t ip4);
150 :
151 : int32_t writeIPADDR(const boost::asio::ip::address& ipaddress);
152 :
153 : int32_t writeDouble(const double dub);
154 :
155 : int32_t writeString(const std::string& str);
156 :
157 : int32_t writeBinary(const std::string& str);
158 :
159 : int32_t writeXML(const std::string& str);
160 :
161 : int32_t writeUUID(const boost::uuids::uuid& uuid);
162 :
163 : /**
164 : * Reading functions
165 : */
166 :
167 : int32_t readMessageBegin(std::string& name,
168 : TMessageType& messageType,
169 : int32_t& seqid);
170 :
171 : int32_t readMessageEnd();
172 :
173 : int32_t readSandeshBegin(std::string& name);
174 :
175 : int32_t readSandeshEnd();
176 :
177 : int32_t readStructBegin(std::string& name);
178 :
179 : int32_t readStructEnd();
180 :
181 : int32_t readContainerElementBegin();
182 :
183 : int32_t readContainerElementEnd();
184 :
185 : int32_t readFieldBegin(std::string& name,
186 : TType& fieldType,
187 : int16_t& fieldId);
188 :
189 : int32_t readFieldEnd();
190 :
191 : int32_t readMapBegin(TType& keyType,
192 : TType& valType,
193 : uint32_t& size);
194 :
195 : int32_t readMapEnd();
196 :
197 : int32_t readListBegin(TType& elemType,
198 : uint32_t& size);
199 :
200 : int32_t readListEnd();
201 :
202 : int32_t readSetBegin(TType& elemType,
203 : uint32_t& size);
204 :
205 : int32_t readSetEnd();
206 :
207 : int32_t readBool(bool& value);
208 :
209 : // Provide the default readBool() implementation for std::vector<bool>
210 : using TVirtualProtocol<TXMLProtocol>::readBool;
211 :
212 : int32_t readByte(int8_t& byte);
213 :
214 : int32_t readI16(int16_t& i16);
215 :
216 : int32_t readI32(int32_t& i32);
217 :
218 : int32_t readI64(int64_t& i64);
219 :
220 : int32_t readU16(uint16_t& u16);
221 :
222 : int32_t readU32(uint32_t& u32);
223 :
224 : int32_t readU64(uint64_t& u64);
225 :
226 : int32_t readIPV4(uint32_t& ip4);
227 :
228 : int32_t readIPADDR(boost::asio::ip::address& ipaddress);
229 :
230 : int32_t readDouble(double& dub);
231 :
232 : int32_t readString(std::string& str);
233 :
234 : int32_t readBinary(std::string& str);
235 :
236 : int32_t readXML(std::string& str);
237 :
238 : int32_t readUUID(boost::uuids::uuid& uuid);
239 :
240 : class LookaheadReader {
241 :
242 : public:
243 :
244 : LookaheadReader(TTransport &trans) :
245 : trans_(&trans),
246 : hasData_(false),
247 : has2Data_(false),
248 : firstRead_(false) {
249 : }
250 :
251 147140 : uint8_t read() {
252 147140 : if (hasData_) {
253 21802 : hasData_ = false;
254 : }
255 : else {
256 125338 : if (has2Data_) {
257 4626 : if (firstRead_) {
258 2313 : has2Data_ = false;
259 2313 : firstRead_ = false;
260 2313 : return data2_[1];
261 : } else {
262 2313 : firstRead_ = true;
263 2313 : return data2_[0];
264 : }
265 : } else {
266 120712 : trans_->readAll(&data_, 1);
267 : }
268 : }
269 142514 : return data_;
270 : }
271 :
272 21802 : uint8_t peek() {
273 21802 : if (!hasData_) {
274 21802 : trans_->readAll(&data_, 1);
275 : }
276 21802 : hasData_ = true;
277 21802 : return data_;
278 : }
279 :
280 4626 : uint8_t peek2() {
281 4626 : bool first = false;
282 4626 : if (!has2Data_) {
283 2313 : trans_->readAll(data2_, 2);
284 2313 : first = true;
285 : }
286 4626 : has2Data_ = true;
287 4626 : return first ? data2_[0] : data2_[1];
288 : }
289 :
290 : private:
291 : TTransport *trans_;
292 : bool hasData_;
293 : uint8_t data_;
294 : bool has2Data_;
295 : uint8_t data2_[2];
296 : bool firstRead_;
297 : };
298 :
299 : private:
300 : typedef boost::tokenizer<boost::char_separator<char> >
301 : tokenizer;
302 :
303 : int32_t readXMLSyntaxChar(uint8_t ch);
304 :
305 : int32_t readXMLSyntaxString(const std::string &str);
306 :
307 : int32_t readXMLString(std::string &str);
308 :
309 : int32_t readXMLTag(std::string &str, bool endTag = false);
310 :
311 : int32_t readXMLNumericChars(std::string &str);
312 :
313 : int32_t readXMLCDATA(std::string &str);
314 :
315 : template <typename NumberType>
316 : int32_t readXMLInteger(NumberType &num);
317 :
318 : int32_t readXMLDouble(double &num);
319 :
320 : int32_t readXMLUuid(boost::uuids::uuid &uuid);
321 :
322 : void indentUp();
323 : void indentDown();
324 : int32_t writePlain(const std::string& str);
325 : int32_t writeIndented(const std::string& str);
326 :
327 : static const std::string& fieldTypeName(TType type);
328 : static TType getTypeIDForTypeName(const std::string &name);
329 :
330 : TTransport* trans_;
331 :
332 : int32_t string_limit_;
333 : int32_t string_prefix_size_;
334 :
335 : std::string indent_str_;
336 :
337 : static const int indent_inc = 2;
338 :
339 : std::vector<write_state_t> write_state_;
340 :
341 : std::vector<std::string> xml_state_;
342 : LookaheadReader reader_;
343 : };
344 :
345 : /**
346 : * Constructs XML protocol handlers
347 : */
348 : class TXMLProtocolFactory : public TProtocolFactory {
349 : public:
350 : TXMLProtocolFactory() {}
351 : virtual ~TXMLProtocolFactory() {}
352 :
353 : boost::shared_ptr<TProtocol> getProtocol(boost::shared_ptr<TTransport> trans) {
354 : return boost::shared_ptr<TProtocol>(new TXMLProtocol(trans));
355 : }
356 :
357 : };
358 :
359 : }}} // contrail::sandesh::protocol
360 :
361 : #endif // #ifndef _SANDESH_PROTOCOL_TXMLPROTOCOL_H_
362 :
363 :
|