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